[Mlir-commits] [mlir] 52b34df - [mlir][PDLL] Add an initial language server for PDLL

River Riddle llvmlistbot at llvm.org
Sat Mar 19 13:29:27 PDT 2022


Author: River Riddle
Date: 2022-03-19T13:28:23-07:00
New Revision: 52b34df9d670e948a97dd72b8b5a426d7b3007c7

URL: https://github.com/llvm/llvm-project/commit/52b34df9d670e948a97dd72b8b5a426d7b3007c7
DIFF: https://github.com/llvm/llvm-project/commit/52b34df9d670e948a97dd72b8b5a426d7b3007c7.diff

LOG: [mlir][PDLL] Add an initial language server for PDLL

This commits adds a basic language server for PDLL to enable providing
language features in IDEs such as VSCode. This initial commit only
adds support for tracking definitions, references, and diagnostics, but
followup commits will build upon this to provide more significant behavior.

In addition to the server, this commit also updates mlir-vscode to support
the PDLL language and invoke the server.

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

Added: 
    mlir/include/mlir/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.h
    mlir/lib/Tools/mlir-pdll-lsp-server/CMakeLists.txt
    mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp
    mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.h
    mlir/lib/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.cpp
    mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp
    mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h
    mlir/test/mlir-pdll-lsp-server/definition-split-file.test
    mlir/test/mlir-pdll-lsp-server/definition.test
    mlir/test/mlir-pdll-lsp-server/exit-eof.test
    mlir/test/mlir-pdll-lsp-server/exit-with-shutdown.test
    mlir/test/mlir-pdll-lsp-server/exit-without-shutdown.test
    mlir/test/mlir-pdll-lsp-server/initialize-params-invalid.test
    mlir/test/mlir-pdll-lsp-server/initialize-params.test
    mlir/test/mlir-pdll-lsp-server/references.test
    mlir/tools/mlir-pdll-lsp-server/CMakeLists.txt
    mlir/tools/mlir-pdll-lsp-server/mlir-pdll-lsp-server.cpp
    mlir/utils/vscode/pdll-grammar.json
    mlir/utils/vscode/pdll-language-configuration.json

Modified: 
    mlir/include/mlir/Tools/PDLL/AST/Nodes.h
    mlir/lib/Tools/CMakeLists.txt
    mlir/lib/Tools/PDLL/AST/Nodes.cpp
    mlir/lib/Tools/lsp-server-support/Protocol.h
    mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
    mlir/test/CMakeLists.txt
    mlir/tools/CMakeLists.txt
    mlir/utils/vscode/package-lock.json
    mlir/utils/vscode/package.json
    mlir/utils/vscode/src/configWatcher.ts
    mlir/utils/vscode/src/extension.ts
    mlir/utils/vscode/src/mlirContext.ts

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Tools/PDLL/AST/Nodes.h b/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
index 3eb3caacf85b4..6635dc764e04c 100644
--- a/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
+++ b/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
@@ -131,6 +131,18 @@ class Node {
   /// Print this node to the given stream.
   void print(raw_ostream &os) const;
 
+  /// Walk all of the nodes including, and nested under, this node in pre-order.
+  void walk(function_ref<void(const Node *)> walkFn) const;
+  template <typename WalkFnT, typename ArgT = typename llvm::function_traits<
+                                  WalkFnT>::template arg_t<0>>
+  std::enable_if_t<!std::is_convertible<const Node *, ArgT>::value>
+  walk(WalkFnT &&walkFn) const {
+    walk([&](const Node *node) {
+      if (const ArgT *derivedNode = dyn_cast<ArgT>(node))
+        walkFn(derivedNode);
+    });
+  }
+
 protected:
   Node(TypeID typeID, SMRange loc) : typeID(typeID), loc(loc) {}
 

diff  --git a/mlir/include/mlir/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.h b/mlir/include/mlir/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.h
new file mode 100644
index 0000000000000..a193732166c4a
--- /dev/null
+++ b/mlir/include/mlir/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.h
@@ -0,0 +1,25 @@
+//===- MlirPdllLspServerMain.h - MLIR PDLL Language Server main -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Main entry function for mlir-pdll-lsp-server for when built as standalone
+// binary.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TOOLS_MLIR_PDLL_LSP_SERVER_MLIRPDLLLSPSERVERMAIN_H
+#define MLIR_TOOLS_MLIR_PDLL_LSP_SERVER_MLIRPDLLLSPSERVERMAIN_H
+
+namespace mlir {
+struct LogicalResult;
+
+/// Implementation for tools like `mlir-pdll-lsp-server`.
+LogicalResult MlirPdllLspServerMain(int argc, char **argv);
+
+} // namespace mlir
+
+#endif // MLIR_TOOLS_MLIR_PDLL_LSP_SERVER_MLIRPDLLLSPSERVERMAIN_H

diff  --git a/mlir/lib/Tools/CMakeLists.txt b/mlir/lib/Tools/CMakeLists.txt
index 0c90545da6c58..643fe6a4544dc 100644
--- a/mlir/lib/Tools/CMakeLists.txt
+++ b/mlir/lib/Tools/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(lsp-server-support)
 add_subdirectory(mlir-lsp-server)
 add_subdirectory(mlir-opt)
+add_subdirectory(mlir-pdll-lsp-server)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-translate)
 add_subdirectory(PDLL)

diff  --git a/mlir/lib/Tools/PDLL/AST/Nodes.cpp b/mlir/lib/Tools/PDLL/AST/Nodes.cpp
index 2e7b252b35c86..5f1af1dc7b2eb 100644
--- a/mlir/lib/Tools/PDLL/AST/Nodes.cpp
+++ b/mlir/lib/Tools/PDLL/AST/Nodes.cpp
@@ -9,6 +9,7 @@
 #include "mlir/Tools/PDLL/AST/Nodes.h"
 #include "mlir/Tools/PDLL/AST/Context.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/TypeSwitch.h"
 
 using namespace mlir;
 using namespace mlir::pdll::ast;
@@ -33,6 +34,135 @@ const Name &Name::create(Context &ctx, StringRef name, SMRange location) {
       Name(copyStringWithNull(ctx, name), location);
 }
 
+//===----------------------------------------------------------------------===//
+// Node
+//===----------------------------------------------------------------------===//
+
+namespace {
+class NodeVisitor {
+public:
+  explicit NodeVisitor(function_ref<void(const Node *)> visitFn)
+      : visitFn(visitFn) {}
+
+  void visit(const Node *node) {
+    if (!node || !alreadyVisited.insert(node).second)
+      return;
+
+    visitFn(node);
+    TypeSwitch<const Node *>(node)
+        .Case<
+            // Statements.
+            const CompoundStmt, const EraseStmt, const LetStmt,
+            const ReplaceStmt, const ReturnStmt, const RewriteStmt,
+
+            // Expressions.
+            const AttributeExpr, const CallExpr, const DeclRefExpr,
+            const MemberAccessExpr, const OperationExpr, const TupleExpr,
+            const TypeExpr,
+
+            // Core Constraint Decls.
+            const AttrConstraintDecl, const OpConstraintDecl,
+            const TypeConstraintDecl, const TypeRangeConstraintDecl,
+            const ValueConstraintDecl, const ValueRangeConstraintDecl,
+
+            // Decls.
+            const NamedAttributeDecl, const OpNameDecl, const PatternDecl,
+            const UserConstraintDecl, const UserRewriteDecl, const VariableDecl,
+
+            const Module>(
+            [&](auto derivedNode) { this->visitImpl(derivedNode); })
+        .Default([](const Node *) { llvm_unreachable("unknown AST node"); });
+  }
+
+private:
+  void visitImpl(const CompoundStmt *stmt) {
+    for (const Node *child : stmt->getChildren())
+      visit(child);
+  }
+  void visitImpl(const EraseStmt *stmt) { visit(stmt->getRootOpExpr()); }
+  void visitImpl(const LetStmt *stmt) { visit(stmt->getVarDecl()); }
+  void visitImpl(const ReplaceStmt *stmt) {
+    visit(stmt->getRootOpExpr());
+    for (const Node *child : stmt->getReplExprs())
+      visit(child);
+  }
+  void visitImpl(const ReturnStmt *stmt) { visit(stmt->getResultExpr()); }
+  void visitImpl(const RewriteStmt *stmt) {
+    visit(stmt->getRootOpExpr());
+    visit(stmt->getRewriteBody());
+  }
+
+  void visitImpl(const AttributeExpr *expr) {}
+  void visitImpl(const CallExpr *expr) {
+    visit(expr->getCallableExpr());
+    for (const Node *child : expr->getArguments())
+      visit(child);
+  }
+  void visitImpl(const DeclRefExpr *expr) { visit(expr->getDecl()); }
+  void visitImpl(const MemberAccessExpr *expr) { visit(expr->getParentExpr()); }
+  void visitImpl(const OperationExpr *expr) {
+    visit(expr->getNameDecl());
+    for (const Node *child : expr->getOperands())
+      visit(child);
+    for (const Node *child : expr->getResultTypes())
+      visit(child);
+    for (const Node *child : expr->getAttributes())
+      visit(child);
+  }
+  void visitImpl(const TupleExpr *expr) {
+    for (const Node *child : expr->getElements())
+      visit(child);
+  }
+  void visitImpl(const TypeExpr *expr) {}
+
+  void visitImpl(const AttrConstraintDecl *decl) { visit(decl->getTypeExpr()); }
+  void visitImpl(const OpConstraintDecl *decl) { visit(decl->getNameDecl()); }
+  void visitImpl(const TypeConstraintDecl *decl) {}
+  void visitImpl(const TypeRangeConstraintDecl *decl) {}
+  void visitImpl(const ValueConstraintDecl *decl) {
+    visit(decl->getTypeExpr());
+  }
+  void visitImpl(const ValueRangeConstraintDecl *decl) {
+    visit(decl->getTypeExpr());
+  }
+
+  void visitImpl(const NamedAttributeDecl *decl) { visit(decl->getValue()); }
+  void visitImpl(const OpNameDecl *decl) {}
+  void visitImpl(const PatternDecl *decl) { visit(decl->getBody()); }
+  void visitImpl(const UserConstraintDecl *decl) {
+    for (const Node *child : decl->getInputs())
+      visit(child);
+    for (const Node *child : decl->getResults())
+      visit(child);
+    visit(decl->getBody());
+  }
+  void visitImpl(const UserRewriteDecl *decl) {
+    for (const Node *child : decl->getInputs())
+      visit(child);
+    for (const Node *child : decl->getResults())
+      visit(child);
+    visit(decl->getBody());
+  }
+  void visitImpl(const VariableDecl *decl) {
+    visit(decl->getInitExpr());
+    for (const ConstraintRef &child : decl->getConstraints())
+      visit(child.constraint);
+  }
+
+  void visitImpl(const Module *module) {
+    for (const Node *child : module->getChildren())
+      visit(child);
+  }
+
+  function_ref<void(const Node *)> visitFn;
+  SmallPtrSet<const Node *, 16> alreadyVisited;
+};
+} // namespace
+
+void Node::walk(function_ref<void(const Node *)> walkFn) const {
+  return NodeVisitor(walkFn).visit(this);
+}
+
 //===----------------------------------------------------------------------===//
 // DeclScope
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/Tools/lsp-server-support/Protocol.h b/mlir/lib/Tools/lsp-server-support/Protocol.h
index 79ef3855fa733..6cb1dc4d50f6c 100644
--- a/mlir/lib/Tools/lsp-server-support/Protocol.h
+++ b/mlir/lib/Tools/lsp-server-support/Protocol.h
@@ -26,6 +26,7 @@
 #include "mlir/Support/LLVM.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/JSON.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 #include <bitset>
 #include <memory>
@@ -245,6 +246,13 @@ struct Position {
   Position(int line = 0, int character = 0)
       : line(line), character(character) {}
 
+  /// Construct a position from the given source location.
+  Position(llvm::SourceMgr &mgr, SMLoc loc) {
+    std::pair<unsigned, unsigned> lineAndCol = mgr.getLineAndColumn(loc);
+    line = lineAndCol.first - 1;
+    character = lineAndCol.second - 1;
+  }
+
   /// Line position in a document (zero-based).
   int line = 0;
 
@@ -266,6 +274,13 @@ struct Position {
     return std::tie(lhs.line, lhs.character) <=
            std::tie(rhs.line, rhs.character);
   }
+
+  /// Convert this position into a source location in the main file of the given
+  /// source manager.
+  SMLoc getAsSMLoc(llvm::SourceMgr &mgr) const {
+    return mgr.FindLocForLineAndColumn(mgr.getMainFileID(), line + 1,
+                                       character);
+  }
 };
 
 /// Add support for JSON serialization.
@@ -283,6 +298,10 @@ struct Range {
   Range(Position start, Position end) : start(start), end(end) {}
   Range(Position loc) : Range(loc, loc) {}
 
+  /// Construct a range from the given source range.
+  Range(llvm::SourceMgr &mgr, SMRange range)
+      : Range(Position(mgr, range.Start), Position(mgr, range.End)) {}
+
   /// The range's start position.
   Position start;
 
@@ -316,6 +335,13 @@ raw_ostream &operator<<(raw_ostream &os, const Range &value);
 //===----------------------------------------------------------------------===//
 
 struct Location {
+  Location() = default;
+  Location(const URIForFile &uri, Range range) : uri(uri), range(range) {}
+
+  /// Construct a Location from the given source range.
+  Location(const URIForFile &uri, llvm::SourceMgr &mgr, SMRange range)
+      : Location(uri, Range(mgr, range)) {}
+
   /// The text document's URI.
   URIForFile uri;
   Range range;

diff  --git a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
index 6b6dcc28cddde..cc057d7ffd892 100644
--- a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
+++ b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
@@ -17,32 +17,6 @@
 
 using namespace mlir;
 
-/// Returns a language server position for the given source location.
-static lsp::Position getPosFromLoc(llvm::SourceMgr &mgr, SMLoc loc) {
-  std::pair<unsigned, unsigned> lineAndCol = mgr.getLineAndColumn(loc);
-  lsp::Position pos;
-  pos.line = lineAndCol.first - 1;
-  pos.character = lineAndCol.second - 1;
-  return pos;
-}
-
-/// Returns a source location from the given language server position.
-static SMLoc getPosFromLoc(llvm::SourceMgr &mgr, lsp::Position pos) {
-  return mgr.FindLocForLineAndColumn(mgr.getMainFileID(), pos.line + 1,
-                                     pos.character);
-}
-
-/// Returns a language server range for the given source range.
-static lsp::Range getRangeFromLoc(llvm::SourceMgr &mgr, SMRange range) {
-  return {getPosFromLoc(mgr, range.Start), getPosFromLoc(mgr, range.End)};
-}
-
-/// Returns a language server location from the given source range.
-static lsp::Location getLocationFromLoc(llvm::SourceMgr &mgr, SMRange range,
-                                        const lsp::URIForFile &uri) {
-  return lsp::Location{uri, getRangeFromLoc(mgr, range)};
-}
-
 /// Returns a language server location from the given MLIR file location.
 static Optional<lsp::Location> getLocationFromLoc(FileLineColLoc loc) {
   llvm::Expected<lsp::URIForFile> sourceURI =
@@ -348,13 +322,13 @@ MLIRDocument::MLIRDocument(MLIRContext &context, const lsp::URIForFile &uri,
 void MLIRDocument::getLocationsOf(const lsp::URIForFile &uri,
                                   const lsp::Position &defPos,
                                   std::vector<lsp::Location> &locations) {
-  SMLoc posLoc = getPosFromLoc(sourceMgr, defPos);
+  SMLoc posLoc = defPos.getAsSMLoc(sourceMgr);
 
   // Functor used to check if an SM definition contains the position.
   auto containsPosition = [&](const AsmParserState::SMDefinition &def) {
     if (!isDefOrUse(def, posLoc))
       return false;
-    locations.push_back(getLocationFromLoc(sourceMgr, def.loc, uri));
+    locations.emplace_back(uri, sourceMgr, def.loc);
     return true;
   };
 
@@ -367,7 +341,7 @@ void MLIRDocument::getLocationsOf(const lsp::URIForFile &uri,
         return collectLocationsFromLoc(op.op->getLoc(), locations, uri);
     for (const auto &symUse : op.symbolUses) {
       if (contains(symUse, posLoc)) {
-        locations.push_back(getLocationFromLoc(sourceMgr, op.loc, uri));
+        locations.emplace_back(uri, sourceMgr, op.loc);
         return collectLocationsFromLoc(op.op->getLoc(), locations, uri);
       }
     }
@@ -389,12 +363,12 @@ void MLIRDocument::findReferencesOf(const lsp::URIForFile &uri,
   // Functor used to append all of the definitions/uses of the given SM
   // definition to the reference list.
   auto appendSMDef = [&](const AsmParserState::SMDefinition &def) {
-    references.push_back(getLocationFromLoc(sourceMgr, def.loc, uri));
+    references.emplace_back(uri, sourceMgr, def.loc);
     for (const SMRange &use : def.uses)
-      references.push_back(getLocationFromLoc(sourceMgr, use, uri));
+      references.emplace_back(uri, sourceMgr, use);
   };
 
-  SMLoc posLoc = getPosFromLoc(sourceMgr, pos);
+  SMLoc posLoc = pos.getAsSMLoc(sourceMgr);
 
   // Check all definitions related to operations.
   for (const AsmParserState::OperationDefinition &op : asmState.getOpDefs()) {
@@ -403,7 +377,7 @@ void MLIRDocument::findReferencesOf(const lsp::URIForFile &uri,
         appendSMDef(result.definition);
       for (const auto &symUse : op.symbolUses)
         if (contains(symUse, posLoc))
-          references.push_back(getLocationFromLoc(sourceMgr, symUse, uri));
+          references.emplace_back(uri, sourceMgr, symUse);
       return;
     }
     for (const auto &result : op.resultGroups)
@@ -413,7 +387,7 @@ void MLIRDocument::findReferencesOf(const lsp::URIForFile &uri,
       if (!contains(symUse, posLoc))
         continue;
       for (const auto &symUse : op.symbolUses)
-        references.push_back(getLocationFromLoc(sourceMgr, symUse, uri));
+        references.emplace_back(uri, sourceMgr, symUse);
       return;
     }
   }
@@ -435,7 +409,7 @@ void MLIRDocument::findReferencesOf(const lsp::URIForFile &uri,
 
 Optional<lsp::Hover> MLIRDocument::findHover(const lsp::URIForFile &uri,
                                              const lsp::Position &hoverPos) {
-  SMLoc posLoc = getPosFromLoc(sourceMgr, hoverPos);
+  SMLoc posLoc = hoverPos.getAsSMLoc(sourceMgr);
   SMRange hoverRange;
 
   // Check for Hovers on operations and results.
@@ -482,7 +456,7 @@ Optional<lsp::Hover> MLIRDocument::findHover(const lsp::URIForFile &uri,
 
 Optional<lsp::Hover> MLIRDocument::buildHoverForOperation(
     SMRange hoverRange, const AsmParserState::OperationDefinition &op) {
-  lsp::Hover hover(getRangeFromLoc(sourceMgr, hoverRange));
+  lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
   llvm::raw_string_ostream os(hover.contents.value);
 
   // Add the operation name to the hover.
@@ -518,7 +492,7 @@ lsp::Hover MLIRDocument::buildHoverForOperationResult(SMRange hoverRange,
                                                       unsigned resultStart,
                                                       unsigned resultEnd,
                                                       SMLoc posLoc) {
-  lsp::Hover hover(getRangeFromLoc(sourceMgr, hoverRange));
+  lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
   llvm::raw_string_ostream os(hover.contents.value);
 
   // Add the parent operation name to the hover.
@@ -551,7 +525,7 @@ lsp::Hover MLIRDocument::buildHoverForOperationResult(SMRange hoverRange,
 lsp::Hover
 MLIRDocument::buildHoverForBlock(SMRange hoverRange,
                                  const AsmParserState::BlockDefinition &block) {
-  lsp::Hover hover(getRangeFromLoc(sourceMgr, hoverRange));
+  lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
   llvm::raw_string_ostream os(hover.contents.value);
 
   // Print the given block to the hover output stream.
@@ -583,7 +557,7 @@ MLIRDocument::buildHoverForBlock(SMRange hoverRange,
 lsp::Hover MLIRDocument::buildHoverForBlockArgument(
     SMRange hoverRange, BlockArgument arg,
     const AsmParserState::BlockDefinition &block) {
-  lsp::Hover hover(getRangeFromLoc(sourceMgr, hoverRange));
+  lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
   llvm::raw_string_ostream os(hover.contents.value);
 
   // Display the parent operation, block, the argument number, and the type.
@@ -618,16 +592,16 @@ void MLIRDocument::findDocumentSymbols(
                            isa<FunctionOpInterface>(op)
                                ? lsp::SymbolKind::Function
                                : lsp::SymbolKind::Class,
-                           getRangeFromLoc(sourceMgr, def->scopeLoc),
-                           getRangeFromLoc(sourceMgr, def->loc));
+                           lsp::Range(sourceMgr, def->scopeLoc),
+                           lsp::Range(sourceMgr, def->loc));
       childSymbols = &symbols.back().children;
 
     } else if (op->hasTrait<OpTrait::SymbolTable>()) {
       // Otherwise, if this is a symbol table push an anonymous document symbol.
       symbols.emplace_back("<" + op->getName().getStringRef() + ">",
                            lsp::SymbolKind::Namespace,
-                           getRangeFromLoc(sourceMgr, def->scopeLoc),
-                           getRangeFromLoc(sourceMgr, def->loc));
+                           lsp::Range(sourceMgr, def->scopeLoc),
+                           lsp::Range(sourceMgr, def->loc));
       childSymbols = &symbols.back().children;
     }
   }

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/CMakeLists.txt b/mlir/lib/Tools/mlir-pdll-lsp-server/CMakeLists.txt
new file mode 100644
index 0000000000000..f9ff5470eca0e
--- /dev/null
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/CMakeLists.txt
@@ -0,0 +1,12 @@
+llvm_add_library(MLIRPdllLspServerLib
+  LSPServer.cpp
+  PDLLServer.cpp
+  MlirPdllLspServerMain.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Tools/mlir-pdll-lsp-server
+
+  LINK_LIBS PUBLIC
+  MLIRPDLLParser
+  MLIRLspServerSupportLib
+  )

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp b/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp
new file mode 100644
index 0000000000000..3cb5191e29772
--- /dev/null
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp
@@ -0,0 +1,198 @@
+//===- LSPServer.cpp - PDLL Language Server -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LSPServer.h"
+
+#include "../lsp-server-support/Logging.h"
+#include "../lsp-server-support/Protocol.h"
+#include "../lsp-server-support/Transport.h"
+#include "PDLLServer.h"
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/StringMap.h"
+
+#define DEBUG_TYPE "pdll-lsp-server"
+
+using namespace mlir;
+using namespace mlir::lsp;
+
+//===----------------------------------------------------------------------===//
+// LSPServer
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct LSPServer {
+  LSPServer(PDLLServer &server, JSONTransport &transport)
+      : server(server), transport(transport) {}
+
+  //===--------------------------------------------------------------------===//
+  // Initialization
+
+  void onInitialize(const InitializeParams &params,
+                    Callback<llvm::json::Value> reply);
+  void onInitialized(const InitializedParams &params);
+  void onShutdown(const NoParams &params, Callback<std::nullptr_t> reply);
+
+  //===--------------------------------------------------------------------===//
+  // Document Change
+
+  void onDocumentDidOpen(const DidOpenTextDocumentParams &params);
+  void onDocumentDidClose(const DidCloseTextDocumentParams &params);
+  void onDocumentDidChange(const DidChangeTextDocumentParams &params);
+
+  //===--------------------------------------------------------------------===//
+  // Definitions and References
+
+  void onGoToDefinition(const TextDocumentPositionParams &params,
+                        Callback<std::vector<Location>> reply);
+  void onReference(const ReferenceParams &params,
+                   Callback<std::vector<Location>> reply);
+
+  //===--------------------------------------------------------------------===//
+  // Fields
+  //===--------------------------------------------------------------------===//
+
+  PDLLServer &server;
+  JSONTransport &transport;
+
+  /// An outgoing notification used to send diagnostics to the client when they
+  /// are ready to be processed.
+  OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
+
+  /// Used to indicate that the 'shutdown' request was received from the
+  /// Language Server client.
+  bool shutdownRequestReceived = false;
+};
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// Initialization
+
+void LSPServer::onInitialize(const InitializeParams &params,
+                             Callback<llvm::json::Value> reply) {
+  // Send a response with the capabilities of this server.
+  llvm::json::Object serverCaps{
+      {"textDocumentSync",
+       llvm::json::Object{
+           {"openClose", true},
+           {"change", (int)TextDocumentSyncKind::Full},
+           {"save", true},
+       }},
+      {"definitionProvider", true},
+      {"referencesProvider", true},
+  };
+
+  llvm::json::Object result{
+      {{"serverInfo", llvm::json::Object{{"name", "mlir-pdll-lsp-server"},
+                                         {"version", "0.0.1"}}},
+       {"capabilities", std::move(serverCaps)}}};
+  reply(std::move(result));
+}
+void LSPServer::onInitialized(const InitializedParams &) {}
+void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
+  shutdownRequestReceived = true;
+  reply(nullptr);
+}
+
+//===----------------------------------------------------------------------===//
+// Document Change
+
+void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
+  PublishDiagnosticsParams diagParams(params.textDocument.uri,
+                                      params.textDocument.version);
+  server.addOrUpdateDocument(params.textDocument.uri, params.textDocument.text,
+                             params.textDocument.version,
+                             diagParams.diagnostics);
+
+  // Publish any recorded diagnostics.
+  publishDiagnostics(diagParams);
+}
+void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
+  Optional<int64_t> version = server.removeDocument(params.textDocument.uri);
+  if (!version)
+    return;
+
+  // Empty out the diagnostics shown for this document. This will clear out
+  // anything currently displayed by the client for this document (e.g. in the
+  // "Problems" pane of VSCode).
+  publishDiagnostics(
+      PublishDiagnosticsParams(params.textDocument.uri, *version));
+}
+void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
+  // TODO: We currently only support full document updates, we should refactor
+  // to avoid this.
+  if (params.contentChanges.size() != 1)
+    return;
+  PublishDiagnosticsParams diagParams(params.textDocument.uri,
+                                      params.textDocument.version);
+  server.addOrUpdateDocument(
+      params.textDocument.uri, params.contentChanges.front().text,
+      params.textDocument.version, diagParams.diagnostics);
+
+  // Publish any recorded diagnostics.
+  publishDiagnostics(diagParams);
+}
+
+//===----------------------------------------------------------------------===//
+// Definitions and References
+
+void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
+                                 Callback<std::vector<Location>> reply) {
+  std::vector<Location> locations;
+  server.getLocationsOf(params.textDocument.uri, params.position, locations);
+  reply(std::move(locations));
+}
+
+void LSPServer::onReference(const ReferenceParams &params,
+                            Callback<std::vector<Location>> reply) {
+  std::vector<Location> locations;
+  server.findReferencesOf(params.textDocument.uri, params.position, locations);
+  reply(std::move(locations));
+}
+
+//===----------------------------------------------------------------------===//
+// Entry Point
+//===----------------------------------------------------------------------===//
+
+LogicalResult mlir::lsp::runPdllLSPServer(PDLLServer &server,
+                                          JSONTransport &transport) {
+  LSPServer lspServer(server, transport);
+  MessageHandler messageHandler(transport);
+
+  // Initialization
+  messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
+  messageHandler.notification("initialized", &lspServer,
+                              &LSPServer::onInitialized);
+  messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
+
+  // Document Changes
+  messageHandler.notification("textDocument/didOpen", &lspServer,
+                              &LSPServer::onDocumentDidOpen);
+  messageHandler.notification("textDocument/didClose", &lspServer,
+                              &LSPServer::onDocumentDidClose);
+  messageHandler.notification("textDocument/didChange", &lspServer,
+                              &LSPServer::onDocumentDidChange);
+
+  // Definitions and References
+  messageHandler.method("textDocument/definition", &lspServer,
+                        &LSPServer::onGoToDefinition);
+  messageHandler.method("textDocument/references", &lspServer,
+                        &LSPServer::onReference);
+
+  // Diagnostics
+  lspServer.publishDiagnostics =
+      messageHandler.outgoingNotification<PublishDiagnosticsParams>(
+          "textDocument/publishDiagnostics");
+
+  // Run the main loop of the transport.
+  if (llvm::Error error = transport.run(messageHandler)) {
+    Logger::error("Transport error: {0}", error);
+    llvm::consumeError(std::move(error));
+    return failure();
+  }
+  return success(lspServer.shutdownRequestReceived);
+}

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.h b/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.h
new file mode 100644
index 0000000000000..5551c4e3d5c98
--- /dev/null
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.h
@@ -0,0 +1,28 @@
+//===- LSPServer.h - PDLL LSP Server ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_MLIR_TOOLS_MLIRPDLLLSPSERVER_LSPSERVER_H
+#define LIB_MLIR_TOOLS_MLIRPDLLLSPSERVER_LSPSERVER_H
+
+#include <memory>
+
+namespace mlir {
+struct LogicalResult;
+
+namespace lsp {
+class JSONTransport;
+class PDLLServer;
+
+/// Run the main loop of the LSP server using the given PDLL server and
+/// transport.
+LogicalResult runPdllLSPServer(PDLLServer &server, JSONTransport &transport);
+
+} // namespace lsp
+} // namespace mlir
+
+#endif // LIB_MLIR_TOOLS_MLIRPDLLLSPSERVER_LSPSERVER_H

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.cpp b/mlir/lib/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.cpp
new file mode 100644
index 0000000000000..b21786de918b7
--- /dev/null
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.cpp
@@ -0,0 +1,72 @@
+//===- MlirPdllLspServerMain.cpp - MLIR PDLL Language Server main ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.h"
+#include "../lsp-server-support/Logging.h"
+#include "../lsp-server-support/Transport.h"
+#include "LSPServer.h"
+#include "PDLLServer.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Program.h"
+
+using namespace mlir;
+using namespace mlir::lsp;
+
+LogicalResult mlir::MlirPdllLspServerMain(int argc, char **argv) {
+  llvm::cl::opt<JSONStreamStyle> inputStyle{
+      "input-style",
+      llvm::cl::desc("Input JSON stream encoding"),
+      llvm::cl::values(clEnumValN(JSONStreamStyle::Standard, "standard",
+                                  "usual LSP protocol"),
+                       clEnumValN(JSONStreamStyle::Delimited, "delimited",
+                                  "messages delimited by `// -----` lines, "
+                                  "with // comment support")),
+      llvm::cl::init(JSONStreamStyle::Standard),
+      llvm::cl::Hidden,
+  };
+  llvm::cl::opt<bool> litTest{
+      "lit-test",
+      llvm::cl::desc(
+          "Abbreviation for -input-style=delimited -pretty -log=verbose. "
+          "Intended to simplify lit tests"),
+      llvm::cl::init(false),
+  };
+  llvm::cl::opt<Logger::Level> logLevel{
+      "log",
+      llvm::cl::desc("Verbosity of log messages written to stderr"),
+      llvm::cl::values(
+          clEnumValN(Logger::Level::Error, "error", "Error messages only"),
+          clEnumValN(Logger::Level::Info, "info",
+                     "High level execution tracing"),
+          clEnumValN(Logger::Level::Debug, "verbose", "Low level details")),
+      llvm::cl::init(Logger::Level::Info),
+  };
+  llvm::cl::opt<bool> prettyPrint{
+      "pretty",
+      llvm::cl::desc("Pretty-print JSON output"),
+      llvm::cl::init(false),
+  };
+  llvm::cl::ParseCommandLineOptions(argc, argv, "MLIR LSP Language Server");
+
+  if (litTest) {
+    inputStyle = JSONStreamStyle::Delimited;
+    logLevel = Logger::Level::Debug;
+    prettyPrint = true;
+  }
+
+  // Configure the logger.
+  Logger::setLogLevel(logLevel);
+
+  // Configure the transport used for communication.
+  llvm::sys::ChangeStdinToBinary();
+  JSONTransport transport(stdin, llvm::outs(), inputStyle, prettyPrint);
+
+  // Configure the servers and start the main language server.
+  PDLLServer server;
+  return runPdllLSPServer(server, transport);
+}

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp
new file mode 100644
index 0000000000000..39a99e8ef0185
--- /dev/null
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp
@@ -0,0 +1,523 @@
+//===- PDLLServer.cpp - PDLL Language Server ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PDLLServer.h"
+
+#include "../lsp-server-support/Logging.h"
+#include "../lsp-server-support/Protocol.h"
+#include "mlir/Tools/PDLL/AST/Context.h"
+#include "mlir/Tools/PDLL/AST/Nodes.h"
+#include "mlir/Tools/PDLL/AST/Types.h"
+#include "mlir/Tools/PDLL/ODS/Constraint.h"
+#include "mlir/Tools/PDLL/ODS/Context.h"
+#include "mlir/Tools/PDLL/ODS/Dialect.h"
+#include "mlir/Tools/PDLL/ODS/Operation.h"
+#include "mlir/Tools/PDLL/Parser/Parser.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/TypeSwitch.h"
+#include "llvm/Support/Path.h"
+
+using namespace mlir;
+using namespace mlir::pdll;
+
+/// Returns a language server uri for the given source location. `mainFileURI`
+/// corresponds to the uri for the main file of the source manager.
+static lsp::URIForFile getURIFromLoc(llvm::SourceMgr &mgr, SMRange loc,
+                                     const lsp::URIForFile &mainFileURI) {
+  int bufferId = mgr.FindBufferContainingLoc(loc.Start);
+  if (bufferId == 0 || bufferId == static_cast<int>(mgr.getMainFileID()))
+    return mainFileURI;
+  llvm::Expected<lsp::URIForFile> fileForLoc = lsp::URIForFile::fromFile(
+      mgr.getBufferInfo(bufferId).Buffer->getBufferIdentifier());
+  if (fileForLoc)
+    return *fileForLoc;
+  lsp::Logger::error("Failed to create URI for include file: {0}",
+                     llvm::toString(fileForLoc.takeError()));
+  return mainFileURI;
+}
+
+/// Returns a language server location from the given source range.
+static lsp::Location getLocationFromLoc(llvm::SourceMgr &mgr, SMRange range,
+                                        const lsp::URIForFile &uri) {
+  return lsp::Location(getURIFromLoc(mgr, range, uri), lsp::Range(mgr, range));
+}
+
+/// Convert the given MLIR diagnostic to the LSP form.
+static Optional<lsp::Diagnostic>
+getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr, const ast::Diagnostic &diag,
+                        const lsp::URIForFile &uri) {
+  lsp::Diagnostic lspDiag;
+  lspDiag.source = "pdll";
+
+  // FIXME: Right now all of the diagnostics are treated as parser issues, but
+  // some are parser and some are verifier.
+  lspDiag.category = "Parse Error";
+
+  // Try to grab a file location for this diagnostic.
+  lsp::Location loc = getLocationFromLoc(sourceMgr, diag.getLocation(), uri);
+  lspDiag.range = loc.range;
+
+  // Skip diagnostics that weren't emitted within the main file.
+  if (loc.uri != uri)
+    return llvm::None;
+
+  // Convert the severity for the diagnostic.
+  switch (diag.getSeverity()) {
+  case ast::Diagnostic::Severity::DK_Note:
+    llvm_unreachable("expected notes to be handled separately");
+  case ast::Diagnostic::Severity::DK_Warning:
+    lspDiag.severity = lsp::DiagnosticSeverity::Warning;
+    break;
+  case ast::Diagnostic::Severity::DK_Error:
+    lspDiag.severity = lsp::DiagnosticSeverity::Error;
+    break;
+  case ast::Diagnostic::Severity::DK_Remark:
+    lspDiag.severity = lsp::DiagnosticSeverity::Information;
+    break;
+  }
+  lspDiag.message = diag.getMessage().str();
+
+  // Attach any notes to the main diagnostic as related information.
+  std::vector<lsp::DiagnosticRelatedInformation> relatedDiags;
+  for (const ast::Diagnostic &note : diag.getNotes()) {
+    relatedDiags.emplace_back(
+        getLocationFromLoc(sourceMgr, note.getLocation(), uri),
+        note.getMessage().str());
+  }
+  if (!relatedDiags.empty())
+    lspDiag.relatedInformation = std::move(relatedDiags);
+
+  return lspDiag;
+}
+
+//===----------------------------------------------------------------------===//
+// PDLIndex
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct PDLIndexSymbol {
+  explicit PDLIndexSymbol(const ast::Decl *definition)
+      : definition(definition) {}
+  explicit PDLIndexSymbol(const ods::Operation *definition)
+      : definition(definition) {}
+
+  /// Return the location of the definition of this symbol.
+  SMRange getDefLoc() const {
+    if (const ast::Decl *decl = definition.dyn_cast<const ast::Decl *>()) {
+      const ast::Name *declName = decl->getName();
+      return declName ? declName->getLoc() : decl->getLoc();
+    }
+    return definition.get<const ods::Operation *>()->getLoc();
+  }
+
+  /// The main definition of the symbol.
+  PointerUnion<const ast::Decl *, const ods::Operation *> definition;
+  /// The set of references to the symbol.
+  std::vector<SMRange> references;
+};
+
+/// This class provides an index for definitions/uses within a PDL document.
+/// It provides efficient lookup of a definition given an input source range.
+class PDLIndex {
+public:
+  PDLIndex() : intervalMap(allocator) {}
+
+  /// Initialize the index with the given ast::Module.
+  void initialize(const ast::Module &module, const ods::Context &odsContext);
+
+  /// Lookup a symbol for the given location. Returns nullptr if no symbol could
+  /// be found. If provided, `overlappedRange` is set to the range that the
+  /// provided `loc` overlapped with.
+  const PDLIndexSymbol *lookup(SMLoc loc,
+                               SMRange *overlappedRange = nullptr) const;
+
+private:
+  /// The type of interval map used to store source references. SMRange is
+  /// half-open, so we also need to use a half-open interval map.
+  using MapT =
+      llvm::IntervalMap<const char *, const PDLIndexSymbol *,
+                        llvm::IntervalMapImpl::NodeSizer<
+                            const char *, const PDLIndexSymbol *>::LeafSize,
+                        llvm::IntervalMapHalfOpenInfo<const char *>>;
+
+  /// An allocator for the interval map.
+  MapT::Allocator allocator;
+
+  /// An interval map containing a corresponding definition mapped to a source
+  /// interval.
+  MapT intervalMap;
+
+  /// A mapping between definitions and their corresponding symbol.
+  DenseMap<const void *, std::unique_ptr<PDLIndexSymbol>> defToSymbol;
+};
+} // namespace
+
+void PDLIndex::initialize(const ast::Module &module,
+                          const ods::Context &odsContext) {
+  auto getOrInsertDef = [&](const auto *def) -> PDLIndexSymbol * {
+    auto it = defToSymbol.try_emplace(def, nullptr);
+    if (it.second)
+      it.first->second = std::make_unique<PDLIndexSymbol>(def);
+    return &*it.first->second;
+  };
+  auto insertDeclRef = [&](PDLIndexSymbol *sym, SMRange refLoc,
+                           bool isDef = false) {
+    const char *startLoc = refLoc.Start.getPointer();
+    const char *endLoc = refLoc.End.getPointer();
+    if (!intervalMap.overlaps(startLoc, endLoc)) {
+      intervalMap.insert(startLoc, endLoc, sym);
+      if (!isDef)
+        sym->references.push_back(refLoc);
+    }
+  };
+  auto insertODSOpRef = [&](StringRef opName, SMRange refLoc) {
+    const ods::Operation *odsOp = odsContext.lookupOperation(opName);
+    if (!odsOp)
+      return;
+
+    PDLIndexSymbol *symbol = getOrInsertDef(odsOp);
+    insertDeclRef(symbol, odsOp->getLoc(), /*isDef=*/true);
+    insertDeclRef(symbol, refLoc);
+  };
+
+  module.walk([&](const ast::Node *node) {
+    // Handle references to PDL decls.
+    if (const auto *decl = dyn_cast<ast::OpNameDecl>(node)) {
+      if (Optional<StringRef> name = decl->getName())
+        insertODSOpRef(*name, decl->getLoc());
+    } else if (const ast::Decl *decl = dyn_cast<ast::Decl>(node)) {
+      const ast::Name *name = decl->getName();
+      if (!name)
+        return;
+      PDLIndexSymbol *declSym = getOrInsertDef(decl);
+      insertDeclRef(declSym, name->getLoc(), /*isDef=*/true);
+
+      if (const auto *varDecl = dyn_cast<ast::VariableDecl>(decl)) {
+        // Record references to any constraints.
+        for (const auto &it : varDecl->getConstraints())
+          insertDeclRef(getOrInsertDef(it.constraint), it.referenceLoc);
+      }
+    } else if (const auto *expr = dyn_cast<ast::DeclRefExpr>(node)) {
+      insertDeclRef(getOrInsertDef(expr->getDecl()), expr->getLoc());
+    }
+  });
+}
+
+const PDLIndexSymbol *PDLIndex::lookup(SMLoc loc,
+                                       SMRange *overlappedRange) const {
+  auto it = intervalMap.find(loc.getPointer());
+  if (!it.valid() || loc.getPointer() < it.start())
+    return nullptr;
+
+  if (overlappedRange) {
+    *overlappedRange = SMRange(SMLoc::getFromPointer(it.start()),
+                               SMLoc::getFromPointer(it.stop()));
+  }
+  return it.value();
+}
+
+//===----------------------------------------------------------------------===//
+// PDLDocument
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// This class represents all of the information pertaining to a specific PDL
+/// document.
+struct PDLDocument {
+  PDLDocument(const lsp::URIForFile &uri, StringRef contents,
+              std::vector<lsp::Diagnostic> &diagnostics);
+  PDLDocument(const PDLDocument &) = delete;
+  PDLDocument &operator=(const PDLDocument &) = delete;
+
+  //===--------------------------------------------------------------------===//
+  // Definitions and References
+  //===--------------------------------------------------------------------===//
+
+  void getLocationsOf(const lsp::URIForFile &uri, const lsp::Position &defPos,
+                      std::vector<lsp::Location> &locations);
+  void findReferencesOf(const lsp::URIForFile &uri, const lsp::Position &pos,
+                        std::vector<lsp::Location> &references);
+
+  //===--------------------------------------------------------------------===//
+  // Fields
+  //===--------------------------------------------------------------------===//
+
+  /// The include directories for this file.
+  std::vector<std::string> includeDirs;
+
+  /// The source manager containing the contents of the input file.
+  llvm::SourceMgr sourceMgr;
+
+  /// The ODS and AST contexts.
+  ods::Context odsContext;
+  ast::Context astContext;
+
+  /// The parsed AST module, or failure if the file wasn't valid.
+  FailureOr<ast::Module *> astModule;
+
+  /// The index of the parsed module.
+  PDLIndex index;
+};
+} // namespace
+
+PDLDocument::PDLDocument(const lsp::URIForFile &uri, StringRef contents,
+                         std::vector<lsp::Diagnostic> &diagnostics)
+    : astContext(odsContext) {
+  auto memBuffer = llvm::MemoryBuffer::getMemBufferCopy(contents, uri.file());
+  if (!memBuffer) {
+    lsp::Logger::error("Failed to create memory buffer for file", uri.file());
+    return;
+  }
+
+  // TODO: Properly provide include directories from the client.
+  llvm::SmallString<32> uriDirectory(uri.file());
+  llvm::sys::path::remove_filename(uriDirectory);
+  includeDirs.push_back(uriDirectory.str().str());
+
+  sourceMgr.setIncludeDirs(includeDirs);
+  sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
+
+  astContext.getDiagEngine().setHandlerFn([&](const ast::Diagnostic &diag) {
+    if (auto lspDiag = getLspDiagnoticFromDiag(sourceMgr, diag, uri))
+      diagnostics.push_back(std::move(*lspDiag));
+  });
+  astModule = parsePDLAST(astContext, sourceMgr);
+  if (succeeded(astModule))
+    index.initialize(**astModule, odsContext);
+}
+
+//===----------------------------------------------------------------------===//
+// PDLDocument: Definitions and References
+//===----------------------------------------------------------------------===//
+
+void PDLDocument::getLocationsOf(const lsp::URIForFile &uri,
+                                 const lsp::Position &defPos,
+                                 std::vector<lsp::Location> &locations) {
+  SMLoc posLoc = defPos.getAsSMLoc(sourceMgr);
+  const PDLIndexSymbol *symbol = index.lookup(posLoc);
+  if (!symbol)
+    return;
+
+  locations.push_back(getLocationFromLoc(sourceMgr, symbol->getDefLoc(), uri));
+}
+
+void PDLDocument::findReferencesOf(const lsp::URIForFile &uri,
+                                   const lsp::Position &pos,
+                                   std::vector<lsp::Location> &references) {
+  SMLoc posLoc = pos.getAsSMLoc(sourceMgr);
+  const PDLIndexSymbol *symbol = index.lookup(posLoc);
+  if (!symbol)
+    return;
+
+  references.push_back(getLocationFromLoc(sourceMgr, symbol->getDefLoc(), uri));
+  for (SMRange refLoc : symbol->references)
+    references.push_back(getLocationFromLoc(sourceMgr, refLoc, uri));
+}
+
+//===----------------------------------------------------------------------===//
+// PDLTextFileChunk
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// This class represents a single chunk of an PDL text file.
+struct PDLTextFileChunk {
+  PDLTextFileChunk(uint64_t lineOffset, const lsp::URIForFile &uri,
+                   StringRef contents,
+                   std::vector<lsp::Diagnostic> &diagnostics)
+      : lineOffset(lineOffset), document(uri, contents, diagnostics) {}
+
+  /// Adjust the line number of the given range to anchor at the beginning of
+  /// the file, instead of the beginning of this chunk.
+  void adjustLocForChunkOffset(lsp::Range &range) {
+    adjustLocForChunkOffset(range.start);
+    adjustLocForChunkOffset(range.end);
+  }
+  /// Adjust the line number of the given position to anchor at the beginning of
+  /// the file, instead of the beginning of this chunk.
+  void adjustLocForChunkOffset(lsp::Position &pos) { pos.line += lineOffset; }
+
+  /// The line offset of this chunk from the beginning of the file.
+  uint64_t lineOffset;
+  /// The document referred to by this chunk.
+  PDLDocument document;
+};
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// PDLTextFile
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// This class represents a text file containing one or more PDL documents.
+class PDLTextFile {
+public:
+  PDLTextFile(const lsp::URIForFile &uri, StringRef fileContents,
+              int64_t version, std::vector<lsp::Diagnostic> &diagnostics);
+
+  /// Return the current version of this text file.
+  int64_t getVersion() const { return version; }
+
+  //===--------------------------------------------------------------------===//
+  // LSP Queries
+  //===--------------------------------------------------------------------===//
+
+  void getLocationsOf(const lsp::URIForFile &uri, lsp::Position defPos,
+                      std::vector<lsp::Location> &locations);
+  void findReferencesOf(const lsp::URIForFile &uri, lsp::Position pos,
+                        std::vector<lsp::Location> &references);
+
+private:
+  /// Find the PDL document that contains the given position, and update the
+  /// position to be anchored at the start of the found chunk instead of the
+  /// beginning of the file.
+  PDLTextFileChunk &getChunkFor(lsp::Position &pos);
+
+  /// The full string contents of the file.
+  std::string contents;
+
+  /// The version of this file.
+  int64_t version;
+
+  /// The number of lines in the file.
+  int64_t totalNumLines;
+
+  /// The chunks of this file. The order of these chunks is the order in which
+  /// they appear in the text file.
+  std::vector<std::unique_ptr<PDLTextFileChunk>> chunks;
+};
+} // namespace
+
+PDLTextFile::PDLTextFile(const lsp::URIForFile &uri, StringRef fileContents,
+                         int64_t version,
+                         std::vector<lsp::Diagnostic> &diagnostics)
+    : contents(fileContents.str()), version(version), totalNumLines(0) {
+  // Split the file into separate PDL documents.
+  // TODO: Find a way to share the split file marker with other tools. We don't
+  // want to use `splitAndProcessBuffer` here, but we do want to make sure this
+  // marker doesn't go out of sync.
+  SmallVector<StringRef, 8> subContents;
+  StringRef(contents).split(subContents, "// -----");
+  chunks.emplace_back(std::make_unique<PDLTextFileChunk>(
+      /*lineOffset=*/0, uri, subContents.front(), diagnostics));
+
+  uint64_t lineOffset = subContents.front().count('\n');
+  for (StringRef docContents : llvm::drop_begin(subContents)) {
+    unsigned currentNumDiags = diagnostics.size();
+    auto chunk = std::make_unique<PDLTextFileChunk>(lineOffset, uri,
+                                                    docContents, diagnostics);
+    lineOffset += docContents.count('\n');
+
+    // Adjust locations used in diagnostics to account for the offset from the
+    // beginning of the file.
+    for (lsp::Diagnostic &diag :
+         llvm::drop_begin(diagnostics, currentNumDiags)) {
+      chunk->adjustLocForChunkOffset(diag.range);
+
+      if (!diag.relatedInformation)
+        continue;
+      for (auto &it : *diag.relatedInformation)
+        if (it.location.uri == uri)
+          chunk->adjustLocForChunkOffset(it.location.range);
+    }
+    chunks.emplace_back(std::move(chunk));
+  }
+  totalNumLines = lineOffset;
+}
+
+void PDLTextFile::getLocationsOf(const lsp::URIForFile &uri,
+                                 lsp::Position defPos,
+                                 std::vector<lsp::Location> &locations) {
+  PDLTextFileChunk &chunk = getChunkFor(defPos);
+  chunk.document.getLocationsOf(uri, defPos, locations);
+
+  // Adjust any locations within this file for the offset of this chunk.
+  if (chunk.lineOffset == 0)
+    return;
+  for (lsp::Location &loc : locations)
+    if (loc.uri == uri)
+      chunk.adjustLocForChunkOffset(loc.range);
+}
+
+void PDLTextFile::findReferencesOf(const lsp::URIForFile &uri,
+                                   lsp::Position pos,
+                                   std::vector<lsp::Location> &references) {
+  PDLTextFileChunk &chunk = getChunkFor(pos);
+  chunk.document.findReferencesOf(uri, pos, references);
+
+  // Adjust any locations within this file for the offset of this chunk.
+  if (chunk.lineOffset == 0)
+    return;
+  for (lsp::Location &loc : references)
+    if (loc.uri == uri)
+      chunk.adjustLocForChunkOffset(loc.range);
+}
+
+PDLTextFileChunk &PDLTextFile::getChunkFor(lsp::Position &pos) {
+  if (chunks.size() == 1)
+    return *chunks.front();
+
+  // Search for the first chunk with a greater line offset, the previous chunk
+  // is the one that contains `pos`.
+  auto it = llvm::upper_bound(
+      chunks, pos, [](const lsp::Position &pos, const auto &chunk) {
+        return static_cast<uint64_t>(pos.line) < chunk->lineOffset;
+      });
+  PDLTextFileChunk &chunk = it == chunks.end() ? *chunks.back() : **(--it);
+  pos.line -= chunk.lineOffset;
+  return chunk;
+}
+
+//===----------------------------------------------------------------------===//
+// PDLLServer::Impl
+//===----------------------------------------------------------------------===//
+
+struct lsp::PDLLServer::Impl {
+  /// The files held by the server, mapped by their URI file name.
+  llvm::StringMap<std::unique_ptr<PDLTextFile>> files;
+};
+
+//===----------------------------------------------------------------------===//
+// PDLLServer
+//===----------------------------------------------------------------------===//
+
+lsp::PDLLServer::PDLLServer() : impl(std::make_unique<Impl>()) {}
+lsp::PDLLServer::~PDLLServer() = default;
+
+void lsp::PDLLServer::addOrUpdateDocument(
+    const URIForFile &uri, StringRef contents, int64_t version,
+    std::vector<Diagnostic> &diagnostics) {
+  impl->files[uri.file()] =
+      std::make_unique<PDLTextFile>(uri, contents, version, diagnostics);
+}
+
+Optional<int64_t> lsp::PDLLServer::removeDocument(const URIForFile &uri) {
+  auto it = impl->files.find(uri.file());
+  if (it == impl->files.end())
+    return llvm::None;
+
+  int64_t version = it->second->getVersion();
+  impl->files.erase(it);
+  return version;
+}
+
+void lsp::PDLLServer::getLocationsOf(const URIForFile &uri,
+                                     const Position &defPos,
+                                     std::vector<Location> &locations) {
+  auto fileIt = impl->files.find(uri.file());
+  if (fileIt != impl->files.end())
+    fileIt->second->getLocationsOf(uri, defPos, locations);
+}
+
+void lsp::PDLLServer::findReferencesOf(const URIForFile &uri,
+                                       const Position &pos,
+                                       std::vector<Location> &references) {
+  auto fileIt = impl->files.find(uri.file());
+  if (fileIt != impl->files.end())
+    fileIt->second->findReferencesOf(uri, pos, references);
+}

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h
new file mode 100644
index 0000000000000..7dee92f8a68a9
--- /dev/null
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h
@@ -0,0 +1,59 @@
+//===- PDLLServer.h - PDL General Language Server ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_MLIR_TOOLS_MLIRPDLLSPSERVER_SERVER_H_
+#define LIB_MLIR_TOOLS_MLIRPDLLSPSERVER_SERVER_H_
+
+#include "mlir/Support/LLVM.h"
+#include <memory>
+
+namespace mlir {
+namespace lsp {
+struct Diagnostic;
+struct Location;
+struct Position;
+class URIForFile;
+
+/// This class implements all of the PDLL related functionality necessary for a
+/// language server. This class allows for keeping the PDLL specific logic
+/// separate from the logic that involves LSP server/client communication.
+class PDLLServer {
+public:
+  PDLLServer();
+  ~PDLLServer();
+
+  /// Add or update the document, with the provided `version`, at the given URI.
+  /// Any diagnostics emitted for this document should be added to
+  /// `diagnostics`.
+  void addOrUpdateDocument(const URIForFile &uri, StringRef contents,
+                           int64_t version,
+                           std::vector<Diagnostic> &diagnostics);
+
+  /// Remove the document with the given uri. Returns the version of the removed
+  /// document, or None if the uri did not have a corresponding document within
+  /// the server.
+  Optional<int64_t> removeDocument(const URIForFile &uri);
+
+  /// Return the locations of the object pointed at by the given position.
+  void getLocationsOf(const URIForFile &uri, const Position &defPos,
+                      std::vector<Location> &locations);
+
+  /// Find all references of the object pointed at by the given position.
+  void findReferencesOf(const URIForFile &uri, const Position &pos,
+                        std::vector<Location> &references);
+
+private:
+  struct Impl;
+
+  std::unique_ptr<Impl> impl;
+};
+
+} // namespace lsp
+} // namespace mlir
+
+#endif // LIB_MLIR_TOOLS_MLIRPDLLSPSERVER_SERVER_H_

diff  --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index 24adcb646d08c..3e4606e361551 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -82,6 +82,7 @@ set(MLIR_TEST_DEPENDS
   mlir-capi-pdl-test
   mlir-linalg-ods-yaml-gen
   mlir-lsp-server
+  mlir-pdll-lsp-server
   mlir-opt
   mlir-pdll
   mlir-reduce

diff  --git a/mlir/test/mlir-pdll-lsp-server/definition-split-file.test b/mlir/test/mlir-pdll-lsp-server/definition-split-file.test
new file mode 100644
index 0000000000000..0bbcab468f1d2
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/definition-split-file.test
@@ -0,0 +1,37 @@
+// RUN: mlir-pdll-lsp-server -lit-test < %s | FileCheck %s
+// This test checks support for split files by attempting to find the definition
+// of a symbol in a split file. The interesting part of this test is that the
+// file chunk before the one we are looking for the definition in has an error.
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"pdll","capabilities":{},"trace":"off"}}
+// -----
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{
+  "uri":"test:///foo.pdll",
+  "languageId":"pdll",
+  "version":1,
+  "text":"Pattern Foo {\n// -----\nPattern {\n  erase root: Op<toy.test>;\n }"
+}}}
+// -----
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{
+  "textDocument":{"uri":"test:///foo.pdll"},
+  "position":{"line":3,"character":12}
+}}
+//      CHECK:  "id": 1
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": [
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 12,
+// CHECK-NEXT:          "line": 3
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 8,
+// CHECK-NEXT:          "line": 3
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    }
+// -----
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+// -----
+{"jsonrpc":"2.0","method":"exit"}

diff  --git a/mlir/test/mlir-pdll-lsp-server/definition.test b/mlir/test/mlir-pdll-lsp-server/definition.test
new file mode 100644
index 0000000000000..d978737102c56
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/definition.test
@@ -0,0 +1,55 @@
+// RUN: mlir-pdll-lsp-server -lit-test < %s | FileCheck %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"pdll","capabilities":{},"trace":"off"}}
+// -----
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{
+  "uri":"test:///foo.pdll",
+  "languageId":"pdll",
+  "version":1,
+  "text":"Pattern FooPattern {\nlet root: Op<toy.test>;\nerase root;\n}"
+}}}
+// -----
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{
+  "textDocument":{"uri":"test:///foo.pdll"},
+  "position":{"line":0,"character":12}
+}}
+//      CHECK:  "id": 1
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": [
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 18,
+// CHECK-NEXT:          "line": 0
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 8,
+// CHECK-NEXT:          "line": 0
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    }
+// -----
+{"jsonrpc":"2.0","id":2,"method":"textDocument/definition","params":{
+  "textDocument":{"uri":"test:///foo.pdll"},
+  "position":{"line":2,"character":8}
+}}
+//      CHECK:  "id": 2
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": [
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 8,
+// CHECK-NEXT:          "line": 1
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 4,
+// CHECK-NEXT:          "line": 1
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    }
+// -----
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+// -----
+{"jsonrpc":"2.0","method":"exit"}

diff  --git a/mlir/test/mlir-pdll-lsp-server/exit-eof.test b/mlir/test/mlir-pdll-lsp-server/exit-eof.test
new file mode 100644
index 0000000000000..6681d803f4ce1
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/exit-eof.test
@@ -0,0 +1,7 @@
+// RUN: not mlir-pdll-lsp-server < %s 2> %t.err
+// RUN: FileCheck %s < %t.err
+//
+// No LSP messages here, just let mlir-pdll-lsp-server see the end-of-file
+// CHECK: Transport error:
+// (Typically "Transport error: Input/output error" but platform-dependent).
+

diff  --git a/mlir/test/mlir-pdll-lsp-server/exit-with-shutdown.test b/mlir/test/mlir-pdll-lsp-server/exit-with-shutdown.test
new file mode 100644
index 0000000000000..792868f060e74
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/exit-with-shutdown.test
@@ -0,0 +1,6 @@
+// RUN: mlir-pdll-lsp-server -lit-test < %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"pdll","capabilities":{},"trace":"off"}}
+// -----
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+// -----
+{"jsonrpc":"2.0","method":"exit"}

diff  --git a/mlir/test/mlir-pdll-lsp-server/exit-without-shutdown.test b/mlir/test/mlir-pdll-lsp-server/exit-without-shutdown.test
new file mode 100644
index 0000000000000..fade79b9fb93f
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/exit-without-shutdown.test
@@ -0,0 +1,4 @@
+// RUN: not mlir-pdll-lsp-server -lit-test < %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"pdll","capabilities":{},"trace":"off"}}
+// -----
+{"jsonrpc":"2.0","method":"exit"}

diff  --git a/mlir/test/mlir-pdll-lsp-server/initialize-params-invalid.test b/mlir/test/mlir-pdll-lsp-server/initialize-params-invalid.test
new file mode 100644
index 0000000000000..941144e36d724
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/initialize-params-invalid.test
@@ -0,0 +1,12 @@
+// RUN: mlir-pdll-lsp-server -lit-test < %s | FileCheck %s
+// Test with invalid initialize request parameters
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":"","rootUri":"test:///workspace","capabilities":{},"trace":"verbose"}}
+//      CHECK:  "id": 0,
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": {
+// CHECK-NEXT:    "capabilities": {
+// ...
+// -----
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+// -----
+{"jsonrpc":"2.0","method":"exit"}

diff  --git a/mlir/test/mlir-pdll-lsp-server/initialize-params.test b/mlir/test/mlir-pdll-lsp-server/initialize-params.test
new file mode 100644
index 0000000000000..61c5ce0b0cea7
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/initialize-params.test
@@ -0,0 +1,27 @@
+// RUN: mlir-pdll-lsp-server -lit-test < %s | FileCheck %s
+// Test initialize request parameters with rootUri
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"test:///workspace","capabilities":{},"trace":"off"}}
+//      CHECK:  "id": 0,
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": {
+// CHECK-NEXT:    "capabilities": {
+// CHECK-NEXT:      "definitionProvider": true,
+// CHECK-NEXT:      "referencesProvider": true,
+// CHECK-NEXT:      "textDocumentSync": {
+// CHECK-NEXT:        "change": 1,
+// CHECK-NEXT:        "openClose": true,
+// CHECK-NEXT:        "save": true
+// CHECK-NEXT:      }
+// CHECK-NEXT:    },
+// CHECK-NEXT:    "serverInfo": {
+// CHECK-NEXT:      "name": "mlir-pdll-lsp-server",
+// CHECK-NEXT:      "version": "{{.*}}"
+// CHECK-NEXT:    }
+// CHECK-NEXT:  }
+// -----
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+//      CHECK:  "id": 3,
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": null
+// -----
+{"jsonrpc":"2.0","method":"exit"}

diff  --git a/mlir/test/mlir-pdll-lsp-server/references.test b/mlir/test/mlir-pdll-lsp-server/references.test
new file mode 100644
index 0000000000000..a0125f0ad8ec3
--- /dev/null
+++ b/mlir/test/mlir-pdll-lsp-server/references.test
@@ -0,0 +1,98 @@
+// RUN: mlir-pdll-lsp-server -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"pdll","capabilities":{},"trace":"off"}}
+// -----
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{
+  "uri":"test:///foo.pdll",
+  "languageId":"pdll",
+  "version":1,
+  "text":"Constraint ValueCst(value: Value);\nPattern {\nlet arg: ValueCst;\nlet root = op<test.op>(arg);\nreplace root with arg;\n}"
+}}}
+// -----
+{"jsonrpc":"2.0","id":1,"method":"textDocument/references","params":{
+  "textDocument":{"uri":"test:///foo.pdll"},
+  "position":{"line":0,"character":15},
+  "context":{"includeDeclaration": false}
+}}
+//      CHECK:  "id": 1
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": [
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 19,
+// CHECK-NEXT:          "line": 0
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 11,
+// CHECK-NEXT:          "line": 0
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    },
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 17,
+// CHECK-NEXT:          "line": 2
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 9,
+// CHECK-NEXT:          "line": 2
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    }
+// CHECK-NEXT:  ]
+// -----
+{"jsonrpc":"2.0","id":2,"method":"textDocument/references","params":{
+  "textDocument":{"uri":"test:///foo.pdll"},
+  "position":{"line":2,"character":6},
+  "context":{"includeDeclaration": false}
+}}
+//      CHECK:  "id": 2
+// CHECK-NEXT:  "jsonrpc": "2.0",
+// CHECK-NEXT:  "result": [
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 7,
+// CHECK-NEXT:          "line": 2
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 4,
+// CHECK-NEXT:          "line": 2
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    },
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 26,
+// CHECK-NEXT:          "line": 3
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 23,
+// CHECK-NEXT:          "line": 3
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    },
+// CHECK-NEXT:    {
+// CHECK-NEXT:      "range": {
+// CHECK-NEXT:        "end": {
+// CHECK-NEXT:          "character": 21,
+// CHECK-NEXT:          "line": 4
+// CHECK-NEXT:        },
+// CHECK-NEXT:        "start": {
+// CHECK-NEXT:          "character": 18,
+// CHECK-NEXT:          "line": 4
+// CHECK-NEXT:        }
+// CHECK-NEXT:      },
+// CHECK-NEXT:      "uri": "{{.*}}/foo.pdll"
+// CHECK-NEXT:    }
+// CHECK-NEXT:  ]
+// -----
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+// -----
+{"jsonrpc":"2.0","method":"exit"}

diff  --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt
index 06a582c4e0370..16fa0f03f09dd 100644
--- a/mlir/tools/CMakeLists.txt
+++ b/mlir/tools/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(mlir-lsp-server)
 add_subdirectory(mlir-opt)
 add_subdirectory(mlir-pdll)
+add_subdirectory(mlir-pdll-lsp-server)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-shlib)
 add_subdirectory(mlir-spirv-cpu-runner)

diff  --git a/mlir/tools/mlir-pdll-lsp-server/CMakeLists.txt b/mlir/tools/mlir-pdll-lsp-server/CMakeLists.txt
new file mode 100644
index 0000000000000..901c0a40fcf83
--- /dev/null
+++ b/mlir/tools/mlir-pdll-lsp-server/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LIBS
+  MLIRPdllLspServerLib
+  )
+
+add_llvm_tool(mlir-pdll-lsp-server
+  mlir-pdll-lsp-server.cpp
+
+  DEPENDS
+  ${LIBS}
+  )
+
+target_link_libraries(mlir-pdll-lsp-server PRIVATE ${LIBS})
+llvm_update_compile_flags(mlir-pdll-lsp-server)
+
+mlir_check_all_link_libraries(mlir-pdll-lsp-server)

diff  --git a/mlir/tools/mlir-pdll-lsp-server/mlir-pdll-lsp-server.cpp b/mlir/tools/mlir-pdll-lsp-server/mlir-pdll-lsp-server.cpp
new file mode 100644
index 0000000000000..de50fd3d33817
--- /dev/null
+++ b/mlir/tools/mlir-pdll-lsp-server/mlir-pdll-lsp-server.cpp
@@ -0,0 +1,16 @@
+//===- mlir-pdll-lsp-server.cpp - PDLL Language Server main ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Tools/mlir-pdll-lsp-server/MlirPdllLspServerMain.h"
+
+using namespace mlir;
+
+int main(int argc, char **argv) {
+  return failed(MlirPdllLspServerMain(argc, argv));
+}

diff  --git a/mlir/utils/vscode/package-lock.json b/mlir/utils/vscode/package-lock.json
index 633f2527b23d0..be7458f806c3f 100644
--- a/mlir/utils/vscode/package-lock.json
+++ b/mlir/utils/vscode/package-lock.json
@@ -1,2699 +1,2699 @@
 {
-	"name": "vscode-mlir",
-	"version": "0.0.2",
-	"lockfileVersion": 2,
-	"requires": true,
-	"packages": {
-		"": {
-			"name": "vscode-mlir",
-			"version": "0.0.2",
-			"dependencies": {
-				"chokidar": "3.5.2",
-				"vscode-languageclient": "^5.2.1",
-				"vscode-languageserver-types": "3.16.0"
-			},
-			"devDependencies": {
-				"@types/mocha": "^5.2.0",
-				"@types/node": "^8.0.0",
-				"@types/vscode": "1.52.*",
-				"clang-format": "1.4.0",
-				"tslint": "^5.16.0",
-				"typescript": "^3.5.1",
-				"vsce": "^1.75.0",
-				"vscode-test": "^1.3.0"
-			},
-			"engines": {
-				"vscode": "^1.52.0"
-			}
-		},
-		"node_modules/@babel/code-frame": {
-			"version": "7.14.5",
-			"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
-			"integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
-			"dev": true,
-			"dependencies": {
-				"@babel/highlight": "^7.14.5"
-			},
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@babel/helper-validator-identifier": {
-			"version": "7.14.8",
-			"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz",
-			"integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==",
-			"dev": true,
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@babel/highlight": {
-			"version": "7.14.5",
-			"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
-			"integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
-			"dev": true,
-			"dependencies": {
-				"@babel/helper-validator-identifier": "^7.14.5",
-				"chalk": "^2.0.0",
-				"js-tokens": "^4.0.0"
-			},
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@tootallnate/once": {
-			"version": "1.1.2",
-			"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
-			"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
-			"dev": true,
-			"engines": {
-				"node": ">= 6"
-			}
-		},
-		"node_modules/@types/mocha": {
-			"version": "5.2.7",
-			"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
-			"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
-			"dev": true
-		},
-		"node_modules/@types/node": {
-			"version": "8.10.66",
-			"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz",
-			"integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==",
-			"dev": true
-		},
-		"node_modules/@types/vscode": {
-			"version": "1.52.0",
-			"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.52.0.tgz",
-			"integrity": "sha512-Kt3bvWzAvvF/WH9YEcrCICDp0Z7aHhJGhLJ1BxeyNP6yRjonWqWnAIh35/pXAjswAnWOABrYlF7SwXR9+1nnLA==",
-			"dev": true
-		},
-		"node_modules/agent-base": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
-			"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
-			"dev": true,
-			"dependencies": {
-				"debug": "4"
-			},
-			"engines": {
-				"node": ">= 6.0.0"
-			}
-		},
-		"node_modules/ansi-styles": {
-			"version": "3.2.1",
-			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-			"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-			"dev": true,
-			"dependencies": {
-				"color-convert": "^1.9.0"
-			},
-			"engines": {
-				"node": ">=4"
-			}
-		},
-		"node_modules/anymatch": {
-			"version": "3.1.2",
-			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
-			"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-			"dependencies": {
-				"normalize-path": "^3.0.0",
-				"picomatch": "^2.0.4"
-			},
-			"engines": {
-				"node": ">= 8"
-			}
-		},
-		"node_modules/argparse": {
-			"version": "1.0.10",
-			"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-			"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-			"dev": true,
-			"dependencies": {
-				"sprintf-js": "~1.0.2"
-			}
-		},
-		"node_modules/async": {
-			"version": "1.5.2",
-			"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-			"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
-			"dev": true
-		},
-		"node_modules/azure-devops-node-api": {
-			"version": "11.0.1",
-			"resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz",
-			"integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==",
-			"dev": true,
-			"dependencies": {
-				"tunnel": "0.0.6",
-				"typed-rest-client": "^1.8.4"
-			}
-		},
-		"node_modules/balanced-match": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-			"dev": true
-		},
-		"node_modules/big-integer": {
-			"version": "1.6.48",
-			"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
-			"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
-			"dev": true,
-			"engines": {
-				"node": ">=0.6"
-			}
-		},
-		"node_modules/binary": {
-			"version": "0.3.0",
-			"resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
-			"integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=",
-			"dev": true,
-			"dependencies": {
-				"buffers": "~0.1.1",
-				"chainsaw": "~0.1.0"
-			},
-			"engines": {
-				"node": "*"
-			}
-		},
-		"node_modules/binary-extensions": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-			"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/bluebird": {
-			"version": "3.4.7",
-			"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
-			"integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=",
-			"dev": true
-		},
-		"node_modules/boolbase": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-			"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
-			"dev": true
-		},
-		"node_modules/brace-expansion": {
-			"version": "1.1.11",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-			"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-			"dev": true,
-			"dependencies": {
-				"balanced-match": "^1.0.0",
-				"concat-map": "0.0.1"
-			}
-		},
-		"node_modules/braces": {
-			"version": "3.0.2",
-			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-			"dependencies": {
-				"fill-range": "^7.0.1"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/buffer-crc32": {
-			"version": "0.2.13",
-			"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-			"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
-			"dev": true,
-			"engines": {
-				"node": "*"
-			}
-		},
-		"node_modules/buffer-indexof-polyfill": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
-			"integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
-			"dev": true,
-			"engines": {
-				"node": ">=0.10"
-			}
-		},
-		"node_modules/buffers": {
-			"version": "0.1.1",
-			"resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
-			"integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=",
-			"dev": true,
-			"engines": {
-				"node": ">=0.2.0"
-			}
-		},
-		"node_modules/builtin-modules": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-			"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-			"dev": true,
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/call-bind": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-			"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-			"dev": true,
-			"dependencies": {
-				"function-bind": "^1.1.1",
-				"get-intrinsic": "^1.0.2"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/chainsaw": {
-			"version": "0.1.0",
-			"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
-			"integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=",
-			"dev": true,
-			"dependencies": {
-				"traverse": ">=0.3.0 <0.4"
-			},
-			"engines": {
-				"node": "*"
-			}
-		},
-		"node_modules/chalk": {
-			"version": "2.4.2",
-			"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-			"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-			"dev": true,
-			"dependencies": {
-				"ansi-styles": "^3.2.1",
-				"escape-string-regexp": "^1.0.5",
-				"supports-color": "^5.3.0"
-			},
-			"engines": {
-				"node": ">=4"
-			}
-		},
-		"node_modules/cheerio": {
-			"version": "1.0.0-rc.10",
-			"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
-			"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
-			"dev": true,
-			"dependencies": {
-				"cheerio-select": "^1.5.0",
-				"dom-serializer": "^1.3.2",
-				"domhandler": "^4.2.0",
-				"htmlparser2": "^6.1.0",
-				"parse5": "^6.0.1",
-				"parse5-htmlparser2-tree-adapter": "^6.0.1",
-				"tslib": "^2.2.0"
-			},
-			"engines": {
-				"node": ">= 6"
-			},
-			"funding": {
-				"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
-			}
-		},
-		"node_modules/cheerio-select": {
-			"version": "1.5.0",
-			"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
-			"integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
-			"dev": true,
-			"dependencies": {
-				"css-select": "^4.1.3",
-				"css-what": "^5.0.1",
-				"domelementtype": "^2.2.0",
-				"domhandler": "^4.2.0",
-				"domutils": "^2.7.0"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/fb55"
-			}
-		},
-		"node_modules/cheerio/node_modules/tslib": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
-			"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
-			"dev": true
-		},
-		"node_modules/chokidar": {
-			"version": "3.5.2",
-			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
-			"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
-			"dependencies": {
-				"anymatch": "~3.1.2",
-				"braces": "~3.0.2",
-				"fsevents": "~2.3.2",
-				"glob-parent": "~5.1.2",
-				"is-binary-path": "~2.1.0",
-				"is-glob": "~4.0.1",
-				"normalize-path": "~3.0.0",
-				"readdirp": "~3.6.0"
-			},
-			"engines": {
-				"node": ">= 8.10.0"
-			},
-			"optionalDependencies": {
-				"fsevents": "~2.3.2"
-			}
-		},
-		"node_modules/clang-format": {
-			"version": "1.4.0",
-			"resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.4.0.tgz",
-			"integrity": "sha512-NrdyUnHJOGvMa60vbWk7GJTvOdhibj3uK5C0FlwdNG4301OUvqEJTFce9I9x8qw2odBbIVrJ+9xbsFS3a4FbDA==",
-			"dev": true,
-			"dependencies": {
-				"async": "^1.5.2",
-				"glob": "^7.0.0",
-				"resolve": "^1.1.6"
-			},
-			"bin": {
-				"check-clang-format": "bin/check-clang-format.js",
-				"clang-format": "index.js",
-				"git-clang-format": "bin/git-clang-format"
-			}
-		},
-		"node_modules/color-convert": {
-			"version": "1.9.3",
-			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-			"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-			"dev": true,
-			"dependencies": {
-				"color-name": "1.1.3"
-			}
-		},
-		"node_modules/color-name": {
-			"version": "1.1.3",
-			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-			"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-			"dev": true
-		},
-		"node_modules/commander": {
-			"version": "2.20.3",
-			"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-			"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-			"dev": true
-		},
-		"node_modules/concat-map": {
-			"version": "0.0.1",
-			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-			"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-			"dev": true
-		},
-		"node_modules/core-util-is": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-			"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-			"dev": true
-		},
-		"node_modules/css-select": {
-			"version": "4.1.3",
-			"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
-			"integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
-			"dev": true,
-			"dependencies": {
-				"boolbase": "^1.0.0",
-				"css-what": "^5.0.0",
-				"domhandler": "^4.2.0",
-				"domutils": "^2.6.0",
-				"nth-check": "^2.0.0"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/fb55"
-			}
-		},
-		"node_modules/css-what": {
-			"version": "5.0.1",
-			"resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
-			"integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
-			"dev": true,
-			"engines": {
-				"node": ">= 6"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/fb55"
-			}
-		},
-		"node_modules/debug": {
-			"version": "4.3.2",
-			"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
-			"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
-			"dev": true,
-			"dependencies": {
-				"ms": "2.1.2"
-			},
-			"engines": {
-				"node": ">=6.0"
-			},
-			"peerDependenciesMeta": {
-				"supports-color": {
-					"optional": true
-				}
-			}
-		},
-		"node_modules/denodeify": {
-			"version": "1.2.1",
-			"resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
-			"integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=",
-			"dev": true
-		},
-		"node_modules/
diff ": {
-			"version": "4.0.2",
-			"resolved": "https://registry.npmjs.org/
diff /-/
diff -4.0.2.tgz",
-			"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-			"dev": true,
-			"engines": {
-				"node": ">=0.3.1"
-			}
-		},
-		"node_modules/dom-serializer": {
-			"version": "1.3.2",
-			"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-			"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
-			"dev": true,
-			"dependencies": {
-				"domelementtype": "^2.0.1",
-				"domhandler": "^4.2.0",
-				"entities": "^2.0.0"
-			},
-			"funding": {
-				"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
-			}
-		},
-		"node_modules/domelementtype": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-			"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
-			"dev": true,
-			"funding": [
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/fb55"
-				}
-			]
-		},
-		"node_modules/domhandler": {
-			"version": "4.2.0",
-			"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
-			"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
-			"dev": true,
-			"dependencies": {
-				"domelementtype": "^2.2.0"
-			},
-			"engines": {
-				"node": ">= 4"
-			},
-			"funding": {
-				"url": "https://github.com/fb55/domhandler?sponsor=1"
-			}
-		},
-		"node_modules/domutils": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
-			"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
-			"dev": true,
-			"dependencies": {
-				"dom-serializer": "^1.0.1",
-				"domelementtype": "^2.2.0",
-				"domhandler": "^4.2.0"
-			},
-			"funding": {
-				"url": "https://github.com/fb55/domutils?sponsor=1"
-			}
-		},
-		"node_modules/duplexer2": {
-			"version": "0.1.4",
-			"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
-			"integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
-			"dev": true,
-			"dependencies": {
-				"readable-stream": "^2.0.2"
-			}
-		},
-		"node_modules/entities": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-			"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-			"dev": true,
-			"funding": {
-				"url": "https://github.com/fb55/entities?sponsor=1"
-			}
-		},
-		"node_modules/escape-string-regexp": {
-			"version": "1.0.5",
-			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-			"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-			"dev": true,
-			"engines": {
-				"node": ">=0.8.0"
-			}
-		},
-		"node_modules/esprima": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-			"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-			"dev": true,
-			"bin": {
-				"esparse": "bin/esparse.js",
-				"esvalidate": "bin/esvalidate.js"
-			},
-			"engines": {
-				"node": ">=4"
-			}
-		},
-		"node_modules/fd-slicer": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-			"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
-			"dev": true,
-			"dependencies": {
-				"pend": "~1.2.0"
-			}
-		},
-		"node_modules/fill-range": {
-			"version": "7.0.1",
-			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-			"dependencies": {
-				"to-regex-range": "^5.0.1"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/fs.realpath": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-			"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-			"dev": true
-		},
-		"node_modules/fsevents": {
-			"version": "2.3.2",
-			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
-			"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-			"hasInstallScript": true,
-			"optional": true,
-			"os": [
-				"darwin"
-			],
-			"engines": {
-				"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-			}
-		},
-		"node_modules/fstream": {
-			"version": "1.0.12",
-			"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
-			"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
-			"dev": true,
-			"dependencies": {
-				"graceful-fs": "^4.1.2",
-				"inherits": "~2.0.0",
-				"mkdirp": ">=0.5 0",
-				"rimraf": "2"
-			},
-			"engines": {
-				"node": ">=0.6"
-			}
-		},
-		"node_modules/fstream/node_modules/rimraf": {
-			"version": "2.7.1",
-			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-			"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-			"dev": true,
-			"dependencies": {
-				"glob": "^7.1.3"
-			},
-			"bin": {
-				"rimraf": "bin.js"
-			}
-		},
-		"node_modules/function-bind": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-			"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-			"dev": true
-		},
-		"node_modules/get-intrinsic": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
-			"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
-			"dev": true,
-			"dependencies": {
-				"function-bind": "^1.1.1",
-				"has": "^1.0.3",
-				"has-symbols": "^1.0.1"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/glob": {
-			"version": "7.1.7",
-			"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
-			"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
-			"dev": true,
-			"dependencies": {
-				"fs.realpath": "^1.0.0",
-				"inflight": "^1.0.4",
-				"inherits": "2",
-				"minimatch": "^3.0.4",
-				"once": "^1.3.0",
-				"path-is-absolute": "^1.0.0"
-			},
-			"engines": {
-				"node": "*"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/isaacs"
-			}
-		},
-		"node_modules/glob-parent": {
-			"version": "5.1.2",
-			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-			"dependencies": {
-				"is-glob": "^4.0.1"
-			},
-			"engines": {
-				"node": ">= 6"
-			}
-		},
-		"node_modules/graceful-fs": {
-			"version": "4.2.6",
-			"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-			"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
-			"dev": true
-		},
-		"node_modules/has": {
-			"version": "1.0.3",
-			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-			"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-			"dev": true,
-			"dependencies": {
-				"function-bind": "^1.1.1"
-			},
-			"engines": {
-				"node": ">= 0.4.0"
-			}
-		},
-		"node_modules/has-flag": {
-			"version": "3.0.0",
-			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-			"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-			"dev": true,
-			"engines": {
-				"node": ">=4"
-			}
-		},
-		"node_modules/has-symbols": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
-			"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
-			"dev": true,
-			"engines": {
-				"node": ">= 0.4"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/htmlparser2": {
-			"version": "6.1.0",
-			"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
-			"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
-			"dev": true,
-			"funding": [
-				"https://github.com/fb55/htmlparser2?sponsor=1",
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/fb55"
-				}
-			],
-			"dependencies": {
-				"domelementtype": "^2.0.1",
-				"domhandler": "^4.0.0",
-				"domutils": "^2.5.2",
-				"entities": "^2.0.0"
-			}
-		},
-		"node_modules/http-proxy-agent": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
-			"integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
-			"dev": true,
-			"dependencies": {
-				"@tootallnate/once": "1",
-				"agent-base": "6",
-				"debug": "4"
-			},
-			"engines": {
-				"node": ">= 6"
-			}
-		},
-		"node_modules/https-proxy-agent": {
-			"version": "5.0.0",
-			"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
-			"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
-			"dev": true,
-			"dependencies": {
-				"agent-base": "6",
-				"debug": "4"
-			},
-			"engines": {
-				"node": ">= 6"
-			}
-		},
-		"node_modules/inflight": {
-			"version": "1.0.6",
-			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-			"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-			"dev": true,
-			"dependencies": {
-				"once": "^1.3.0",
-				"wrappy": "1"
-			}
-		},
-		"node_modules/inherits": {
-			"version": "2.0.4",
-			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-			"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-			"dev": true
-		},
-		"node_modules/is-binary-path": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-			"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-			"dependencies": {
-				"binary-extensions": "^2.0.0"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/is-core-module": {
-			"version": "2.5.0",
-			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz",
-			"integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==",
-			"dev": true,
-			"dependencies": {
-				"has": "^1.0.3"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/is-extglob": {
-			"version": "2.1.1",
-			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-			"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/is-glob": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
-			"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
-			"dependencies": {
-				"is-extglob": "^2.1.1"
-			},
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/is-number": {
-			"version": "7.0.0",
-			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-			"engines": {
-				"node": ">=0.12.0"
-			}
-		},
-		"node_modules/isarray": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-			"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-			"dev": true
-		},
-		"node_modules/js-tokens": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-			"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-			"dev": true
-		},
-		"node_modules/js-yaml": {
-			"version": "3.14.1",
-			"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
-			"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
-			"dev": true,
-			"dependencies": {
-				"argparse": "^1.0.7",
-				"esprima": "^4.0.0"
-			},
-			"bin": {
-				"js-yaml": "bin/js-yaml.js"
-			}
-		},
-		"node_modules/leven": {
-			"version": "3.1.0",
-			"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
-			"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
-			"dev": true,
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/linkify-it": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
-			"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
-			"dev": true,
-			"dependencies": {
-				"uc.micro": "^1.0.1"
-			}
-		},
-		"node_modules/listenercount": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
-			"integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=",
-			"dev": true
-		},
-		"node_modules/lodash": {
-			"version": "4.17.21",
-			"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-			"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
-			"dev": true
-		},
-		"node_modules/markdown-it": {
-			"version": "10.0.0",
-			"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
-			"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
-			"dev": true,
-			"dependencies": {
-				"argparse": "^1.0.7",
-				"entities": "~2.0.0",
-				"linkify-it": "^2.0.0",
-				"mdurl": "^1.0.1",
-				"uc.micro": "^1.0.5"
-			},
-			"bin": {
-				"markdown-it": "bin/markdown-it.js"
-			}
-		},
-		"node_modules/markdown-it/node_modules/entities": {
-			"version": "2.0.3",
-			"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
-			"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
-			"dev": true
-		},
-		"node_modules/mdurl": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
-			"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
-			"dev": true
-		},
-		"node_modules/mime": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-			"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-			"dev": true,
-			"bin": {
-				"mime": "cli.js"
-			},
-			"engines": {
-				"node": ">=4"
-			}
-		},
-		"node_modules/minimatch": {
-			"version": "3.0.4",
-			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-			"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-			"dev": true,
-			"dependencies": {
-				"brace-expansion": "^1.1.7"
-			},
-			"engines": {
-				"node": "*"
-			}
-		},
-		"node_modules/minimist": {
-			"version": "1.2.5",
-			"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-			"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-			"dev": true
-		},
-		"node_modules/mkdirp": {
-			"version": "0.5.5",
-			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-			"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-			"dev": true,
-			"dependencies": {
-				"minimist": "^1.2.5"
-			},
-			"bin": {
-				"mkdirp": "bin/cmd.js"
-			}
-		},
-		"node_modules/ms": {
-			"version": "2.1.2",
-			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-			"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-			"dev": true
-		},
-		"node_modules/mute-stream": {
-			"version": "0.0.8",
-			"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
-			"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-			"dev": true
-		},
-		"node_modules/normalize-path": {
-			"version": "3.0.0",
-			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/nth-check": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
-			"integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
-			"dev": true,
-			"dependencies": {
-				"boolbase": "^1.0.0"
-			},
-			"funding": {
-				"url": "https://github.com/fb55/nth-check?sponsor=1"
-			}
-		},
-		"node_modules/object-inspect": {
-			"version": "1.11.0",
-			"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
-			"integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
-			"dev": true,
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/once": {
-			"version": "1.4.0",
-			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-			"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-			"dev": true,
-			"dependencies": {
-				"wrappy": "1"
-			}
-		},
-		"node_modules/os-homedir": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-			"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-			"dev": true,
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/os-tmpdir": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-			"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-			"dev": true,
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/osenv": {
-			"version": "0.1.5",
-			"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
-			"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
-			"dev": true,
-			"dependencies": {
-				"os-homedir": "^1.0.0",
-				"os-tmpdir": "^1.0.0"
-			}
-		},
-		"node_modules/parse-semver": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
-			"integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=",
-			"dev": true,
-			"dependencies": {
-				"semver": "^5.1.0"
-			}
-		},
-		"node_modules/parse5": {
-			"version": "6.0.1",
-			"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-			"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
-			"dev": true
-		},
-		"node_modules/parse5-htmlparser2-tree-adapter": {
-			"version": "6.0.1",
-			"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
-			"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
-			"dev": true,
-			"dependencies": {
-				"parse5": "^6.0.1"
-			}
-		},
-		"node_modules/path-is-absolute": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-			"dev": true,
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/path-parse": {
-			"version": "1.0.7",
-			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-			"dev": true
-		},
-		"node_modules/pend": {
-			"version": "1.2.0",
-			"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-			"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
-			"dev": true
-		},
-		"node_modules/picomatch": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
-			"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
-			"engines": {
-				"node": ">=8.6"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/jonschlinkert"
-			}
-		},
-		"node_modules/process-nextick-args": {
-			"version": "2.0.1",
-			"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
-			"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-			"dev": true
-		},
-		"node_modules/qs": {
-			"version": "6.10.1",
-			"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
-			"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
-			"dev": true,
-			"dependencies": {
-				"side-channel": "^1.0.4"
-			},
-			"engines": {
-				"node": ">=0.6"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/read": {
-			"version": "1.0.7",
-			"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
-			"integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
-			"dev": true,
-			"dependencies": {
-				"mute-stream": "~0.0.4"
-			},
-			"engines": {
-				"node": ">=0.8"
-			}
-		},
-		"node_modules/readable-stream": {
-			"version": "2.3.7",
-			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-			"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-			"dev": true,
-			"dependencies": {
-				"core-util-is": "~1.0.0",
-				"inherits": "~2.0.3",
-				"isarray": "~1.0.0",
-				"process-nextick-args": "~2.0.0",
-				"safe-buffer": "~5.1.1",
-				"string_decoder": "~1.1.1",
-				"util-deprecate": "~1.0.1"
-			}
-		},
-		"node_modules/readdirp": {
-			"version": "3.6.0",
-			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-			"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-			"dependencies": {
-				"picomatch": "^2.2.1"
-			},
-			"engines": {
-				"node": ">=8.10.0"
-			}
-		},
-		"node_modules/resolve": {
-			"version": "1.20.0",
-			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
-			"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
-			"dev": true,
-			"dependencies": {
-				"is-core-module": "^2.2.0",
-				"path-parse": "^1.0.6"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/rimraf": {
-			"version": "3.0.2",
-			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-			"dev": true,
-			"dependencies": {
-				"glob": "^7.1.3"
-			},
-			"bin": {
-				"rimraf": "bin.js"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/isaacs"
-			}
-		},
-		"node_modules/safe-buffer": {
-			"version": "5.1.2",
-			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-			"dev": true
-		},
-		"node_modules/semver": {
-			"version": "5.7.1",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-			"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-			"bin": {
-				"semver": "bin/semver"
-			}
-		},
-		"node_modules/setimmediate": {
-			"version": "1.0.5",
-			"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-			"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
-			"dev": true
-		},
-		"node_modules/side-channel": {
-			"version": "1.0.4",
-			"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-			"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-			"dev": true,
-			"dependencies": {
-				"call-bind": "^1.0.0",
-				"get-intrinsic": "^1.0.2",
-				"object-inspect": "^1.9.0"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/sprintf-js": {
-			"version": "1.0.3",
-			"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-			"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
-			"dev": true
-		},
-		"node_modules/string_decoder": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-			"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-			"dev": true,
-			"dependencies": {
-				"safe-buffer": "~5.1.0"
-			}
-		},
-		"node_modules/supports-color": {
-			"version": "5.5.0",
-			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-			"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-			"dev": true,
-			"dependencies": {
-				"has-flag": "^3.0.0"
-			},
-			"engines": {
-				"node": ">=4"
-			}
-		},
-		"node_modules/tmp": {
-			"version": "0.2.1",
-			"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
-			"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
-			"dev": true,
-			"dependencies": {
-				"rimraf": "^3.0.0"
-			},
-			"engines": {
-				"node": ">=8.17.0"
-			}
-		},
-		"node_modules/to-regex-range": {
-			"version": "5.0.1",
-			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-			"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-			"dependencies": {
-				"is-number": "^7.0.0"
-			},
-			"engines": {
-				"node": ">=8.0"
-			}
-		},
-		"node_modules/traverse": {
-			"version": "0.3.9",
-			"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
-			"integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=",
-			"dev": true,
-			"engines": {
-				"node": "*"
-			}
-		},
-		"node_modules/tslib": {
-			"version": "1.14.1",
-			"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-			"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-			"dev": true
-		},
-		"node_modules/tslint": {
-			"version": "5.20.1",
-			"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
-			"integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==",
-			"dev": true,
-			"dependencies": {
-				"@babel/code-frame": "^7.0.0",
-				"builtin-modules": "^1.1.1",
-				"chalk": "^2.3.0",
-				"commander": "^2.12.1",
-				"
diff ": "^4.0.1",
-				"glob": "^7.1.1",
-				"js-yaml": "^3.13.1",
-				"minimatch": "^3.0.4",
-				"mkdirp": "^0.5.1",
-				"resolve": "^1.3.2",
-				"semver": "^5.3.0",
-				"tslib": "^1.8.0",
-				"tsutils": "^2.29.0"
-			},
-			"bin": {
-				"tslint": "bin/tslint"
-			},
-			"engines": {
-				"node": ">=4.8.0"
-			},
-			"peerDependencies": {
-				"typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev"
-			}
-		},
-		"node_modules/tsutils": {
-			"version": "2.29.0",
-			"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
-			"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
-			"dev": true,
-			"dependencies": {
-				"tslib": "^1.8.1"
-			},
-			"peerDependencies": {
-				"typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
-			}
-		},
-		"node_modules/tunnel": {
-			"version": "0.0.6",
-			"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
-			"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
-			"dev": true,
-			"engines": {
-				"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
-			}
-		},
-		"node_modules/typed-rest-client": {
-			"version": "1.8.4",
-			"resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz",
-			"integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==",
-			"dev": true,
-			"dependencies": {
-				"qs": "^6.9.1",
-				"tunnel": "0.0.6",
-				"underscore": "^1.12.1"
-			}
-		},
-		"node_modules/typescript": {
-			"version": "3.9.10",
-			"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
-			"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
-			"dev": true,
-			"bin": {
-				"tsc": "bin/tsc",
-				"tsserver": "bin/tsserver"
-			},
-			"engines": {
-				"node": ">=4.2.0"
-			}
-		},
-		"node_modules/uc.micro": {
-			"version": "1.0.6",
-			"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
-			"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
-			"dev": true
-		},
-		"node_modules/underscore": {
-			"version": "1.13.1",
-			"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
-			"integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
-			"dev": true
-		},
-		"node_modules/unzipper": {
-			"version": "0.10.11",
-			"resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz",
-			"integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==",
-			"dev": true,
-			"dependencies": {
-				"big-integer": "^1.6.17",
-				"binary": "~0.3.0",
-				"bluebird": "~3.4.1",
-				"buffer-indexof-polyfill": "~1.0.0",
-				"duplexer2": "~0.1.4",
-				"fstream": "^1.0.12",
-				"graceful-fs": "^4.2.2",
-				"listenercount": "~1.0.1",
-				"readable-stream": "~2.3.6",
-				"setimmediate": "~1.0.4"
-			}
-		},
-		"node_modules/url-join": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
-			"integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=",
-			"dev": true
-		},
-		"node_modules/util-deprecate": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-			"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-			"dev": true
-		},
-		"node_modules/vsce": {
-			"version": "1.96.1",
-			"resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz",
-			"integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==",
-			"dev": true,
-			"dependencies": {
-				"azure-devops-node-api": "^11.0.1",
-				"chalk": "^2.4.2",
-				"cheerio": "^1.0.0-rc.9",
-				"commander": "^6.1.0",
-				"denodeify": "^1.2.1",
-				"glob": "^7.0.6",
-				"leven": "^3.1.0",
-				"lodash": "^4.17.15",
-				"markdown-it": "^10.0.0",
-				"mime": "^1.3.4",
-				"minimatch": "^3.0.3",
-				"osenv": "^0.1.3",
-				"parse-semver": "^1.1.1",
-				"read": "^1.0.7",
-				"semver": "^5.1.0",
-				"tmp": "^0.2.1",
-				"typed-rest-client": "^1.8.4",
-				"url-join": "^1.1.0",
-				"yauzl": "^2.3.1",
-				"yazl": "^2.2.2"
-			},
-			"bin": {
-				"vsce": "out/vsce"
-			},
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/vsce/node_modules/commander": {
-			"version": "6.2.1",
-			"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
-			"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
-			"dev": true,
-			"engines": {
-				"node": ">= 6"
-			}
-		},
-		"node_modules/vscode-jsonrpc": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz",
-			"integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==",
-			"engines": {
-				"node": ">=8.0.0 || >=10.0.0"
-			}
-		},
-		"node_modules/vscode-languageclient": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz",
-			"integrity": "sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q==",
-			"dependencies": {
-				"semver": "^5.5.0",
-				"vscode-languageserver-protocol": "3.14.1"
-			},
-			"engines": {
-				"vscode": "^1.30"
-			}
-		},
-		"node_modules/vscode-languageserver-protocol": {
-			"version": "3.14.1",
-			"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz",
-			"integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==",
-			"dependencies": {
-				"vscode-jsonrpc": "^4.0.0",
-				"vscode-languageserver-types": "3.14.0"
-			}
-		},
-		"node_modules/vscode-languageserver-protocol/node_modules/vscode-languageserver-types": {
-			"version": "3.14.0",
-			"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
-			"integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A=="
-		},
-		"node_modules/vscode-languageserver-types": {
-			"version": "3.16.0",
-			"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
-			"integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA=="
-		},
-		"node_modules/vscode-test": {
-			"version": "1.6.1",
-			"resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz",
-			"integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==",
-			"dev": true,
-			"dependencies": {
-				"http-proxy-agent": "^4.0.1",
-				"https-proxy-agent": "^5.0.0",
-				"rimraf": "^3.0.2",
-				"unzipper": "^0.10.11"
-			},
-			"engines": {
-				"node": ">=8.9.3"
-			}
-		},
-		"node_modules/wrappy": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-			"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-			"dev": true
-		},
-		"node_modules/yauzl": {
-			"version": "2.10.0",
-			"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
-			"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
-			"dev": true,
-			"dependencies": {
-				"buffer-crc32": "~0.2.3",
-				"fd-slicer": "~1.1.0"
-			}
-		},
-		"node_modules/yazl": {
-			"version": "2.5.1",
-			"resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
-			"integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
-			"dev": true,
-			"dependencies": {
-				"buffer-crc32": "~0.2.3"
-			}
-		}
-	},
-	"dependencies": {
-		"@babel/code-frame": {
-			"version": "7.14.5",
-			"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
-			"integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
-			"dev": true,
-			"requires": {
-				"@babel/highlight": "^7.14.5"
-			}
-		},
-		"@babel/helper-validator-identifier": {
-			"version": "7.14.8",
-			"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz",
-			"integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==",
-			"dev": true
-		},
-		"@babel/highlight": {
-			"version": "7.14.5",
-			"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
-			"integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
-			"dev": true,
-			"requires": {
-				"@babel/helper-validator-identifier": "^7.14.5",
-				"chalk": "^2.0.0",
-				"js-tokens": "^4.0.0"
-			}
-		},
-		"@tootallnate/once": {
-			"version": "1.1.2",
-			"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
-			"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
-			"dev": true
-		},
-		"@types/mocha": {
-			"version": "5.2.7",
-			"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
-			"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
-			"dev": true
-		},
-		"@types/node": {
-			"version": "8.10.66",
-			"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz",
-			"integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==",
-			"dev": true
-		},
-		"@types/vscode": {
-			"version": "1.52.0",
-			"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.52.0.tgz",
-			"integrity": "sha512-Kt3bvWzAvvF/WH9YEcrCICDp0Z7aHhJGhLJ1BxeyNP6yRjonWqWnAIh35/pXAjswAnWOABrYlF7SwXR9+1nnLA==",
-			"dev": true
-		},
-		"agent-base": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
-			"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
-			"dev": true,
-			"requires": {
-				"debug": "4"
-			}
-		},
-		"ansi-styles": {
-			"version": "3.2.1",
-			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-			"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-			"dev": true,
-			"requires": {
-				"color-convert": "^1.9.0"
-			}
-		},
-		"anymatch": {
-			"version": "3.1.2",
-			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
-			"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-			"requires": {
-				"normalize-path": "^3.0.0",
-				"picomatch": "^2.0.4"
-			}
-		},
-		"argparse": {
-			"version": "1.0.10",
-			"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-			"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-			"dev": true,
-			"requires": {
-				"sprintf-js": "~1.0.2"
-			}
-		},
-		"async": {
-			"version": "1.5.2",
-			"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-			"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
-			"dev": true
-		},
-		"azure-devops-node-api": {
-			"version": "11.0.1",
-			"resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz",
-			"integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==",
-			"dev": true,
-			"requires": {
-				"tunnel": "0.0.6",
-				"typed-rest-client": "^1.8.4"
-			}
-		},
-		"balanced-match": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-			"dev": true
-		},
-		"big-integer": {
-			"version": "1.6.48",
-			"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
-			"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
-			"dev": true
-		},
-		"binary": {
-			"version": "0.3.0",
-			"resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
-			"integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=",
-			"dev": true,
-			"requires": {
-				"buffers": "~0.1.1",
-				"chainsaw": "~0.1.0"
-			}
-		},
-		"binary-extensions": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-			"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
-		},
-		"bluebird": {
-			"version": "3.4.7",
-			"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
-			"integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=",
-			"dev": true
-		},
-		"boolbase": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-			"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
-			"dev": true
-		},
-		"brace-expansion": {
-			"version": "1.1.11",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-			"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-			"dev": true,
-			"requires": {
-				"balanced-match": "^1.0.0",
-				"concat-map": "0.0.1"
-			}
-		},
-		"braces": {
-			"version": "3.0.2",
-			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-			"requires": {
-				"fill-range": "^7.0.1"
-			}
-		},
-		"buffer-crc32": {
-			"version": "0.2.13",
-			"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-			"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
-			"dev": true
-		},
-		"buffer-indexof-polyfill": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
-			"integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
-			"dev": true
-		},
-		"buffers": {
-			"version": "0.1.1",
-			"resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
-			"integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=",
-			"dev": true
-		},
-		"builtin-modules": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-			"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-			"dev": true
-		},
-		"call-bind": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-			"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-			"dev": true,
-			"requires": {
-				"function-bind": "^1.1.1",
-				"get-intrinsic": "^1.0.2"
-			}
-		},
-		"chainsaw": {
-			"version": "0.1.0",
-			"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
-			"integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=",
-			"dev": true,
-			"requires": {
-				"traverse": ">=0.3.0 <0.4"
-			}
-		},
-		"chalk": {
-			"version": "2.4.2",
-			"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-			"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-			"dev": true,
-			"requires": {
-				"ansi-styles": "^3.2.1",
-				"escape-string-regexp": "^1.0.5",
-				"supports-color": "^5.3.0"
-			}
-		},
-		"cheerio": {
-			"version": "1.0.0-rc.10",
-			"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
-			"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
-			"dev": true,
-			"requires": {
-				"cheerio-select": "^1.5.0",
-				"dom-serializer": "^1.3.2",
-				"domhandler": "^4.2.0",
-				"htmlparser2": "^6.1.0",
-				"parse5": "^6.0.1",
-				"parse5-htmlparser2-tree-adapter": "^6.0.1",
-				"tslib": "^2.2.0"
-			},
-			"dependencies": {
-				"tslib": {
-					"version": "2.3.0",
-					"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
-					"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
-					"dev": true
-				}
-			}
-		},
-		"cheerio-select": {
-			"version": "1.5.0",
-			"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
-			"integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
-			"dev": true,
-			"requires": {
-				"css-select": "^4.1.3",
-				"css-what": "^5.0.1",
-				"domelementtype": "^2.2.0",
-				"domhandler": "^4.2.0",
-				"domutils": "^2.7.0"
-			}
-		},
-		"chokidar": {
-			"version": "3.5.2",
-			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
-			"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
-			"requires": {
-				"anymatch": "~3.1.2",
-				"braces": "~3.0.2",
-				"fsevents": "~2.3.2",
-				"glob-parent": "~5.1.2",
-				"is-binary-path": "~2.1.0",
-				"is-glob": "~4.0.1",
-				"normalize-path": "~3.0.0",
-				"readdirp": "~3.6.0"
-			}
-		},
-		"clang-format": {
-			"version": "1.4.0",
-			"resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.4.0.tgz",
-			"integrity": "sha512-NrdyUnHJOGvMa60vbWk7GJTvOdhibj3uK5C0FlwdNG4301OUvqEJTFce9I9x8qw2odBbIVrJ+9xbsFS3a4FbDA==",
-			"dev": true,
-			"requires": {
-				"async": "^1.5.2",
-				"glob": "^7.0.0",
-				"resolve": "^1.1.6"
-			}
-		},
-		"color-convert": {
-			"version": "1.9.3",
-			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-			"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-			"dev": true,
-			"requires": {
-				"color-name": "1.1.3"
-			}
-		},
-		"color-name": {
-			"version": "1.1.3",
-			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-			"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-			"dev": true
-		},
-		"commander": {
-			"version": "2.20.3",
-			"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-			"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-			"dev": true
-		},
-		"concat-map": {
-			"version": "0.0.1",
-			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-			"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-			"dev": true
-		},
-		"core-util-is": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-			"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-			"dev": true
-		},
-		"css-select": {
-			"version": "4.1.3",
-			"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
-			"integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
-			"dev": true,
-			"requires": {
-				"boolbase": "^1.0.0",
-				"css-what": "^5.0.0",
-				"domhandler": "^4.2.0",
-				"domutils": "^2.6.0",
-				"nth-check": "^2.0.0"
-			}
-		},
-		"css-what": {
-			"version": "5.0.1",
-			"resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
-			"integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
-			"dev": true
-		},
-		"debug": {
-			"version": "4.3.2",
-			"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
-			"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
-			"dev": true,
-			"requires": {
-				"ms": "2.1.2"
-			}
-		},
-		"denodeify": {
-			"version": "1.2.1",
-			"resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
-			"integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=",
-			"dev": true
-		},
-		"
diff ": {
-			"version": "4.0.2",
-			"resolved": "https://registry.npmjs.org/
diff /-/
diff -4.0.2.tgz",
-			"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-			"dev": true
-		},
-		"dom-serializer": {
-			"version": "1.3.2",
-			"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-			"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
-			"dev": true,
-			"requires": {
-				"domelementtype": "^2.0.1",
-				"domhandler": "^4.2.0",
-				"entities": "^2.0.0"
-			}
-		},
-		"domelementtype": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-			"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
-			"dev": true
-		},
-		"domhandler": {
-			"version": "4.2.0",
-			"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
-			"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
-			"dev": true,
-			"requires": {
-				"domelementtype": "^2.2.0"
-			}
-		},
-		"domutils": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
-			"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
-			"dev": true,
-			"requires": {
-				"dom-serializer": "^1.0.1",
-				"domelementtype": "^2.2.0",
-				"domhandler": "^4.2.0"
-			}
-		},
-		"duplexer2": {
-			"version": "0.1.4",
-			"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
-			"integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
-			"dev": true,
-			"requires": {
-				"readable-stream": "^2.0.2"
-			}
-		},
-		"entities": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-			"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-			"dev": true
-		},
-		"escape-string-regexp": {
-			"version": "1.0.5",
-			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-			"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-			"dev": true
-		},
-		"esprima": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-			"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-			"dev": true
-		},
-		"fd-slicer": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-			"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
-			"dev": true,
-			"requires": {
-				"pend": "~1.2.0"
-			}
-		},
-		"fill-range": {
-			"version": "7.0.1",
-			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-			"requires": {
-				"to-regex-range": "^5.0.1"
-			}
-		},
-		"fs.realpath": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-			"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-			"dev": true
-		},
-		"fsevents": {
-			"version": "2.3.2",
-			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
-			"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-			"optional": true
-		},
-		"fstream": {
-			"version": "1.0.12",
-			"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
-			"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
-			"dev": true,
-			"requires": {
-				"graceful-fs": "^4.1.2",
-				"inherits": "~2.0.0",
-				"mkdirp": ">=0.5 0",
-				"rimraf": "2"
-			},
-			"dependencies": {
-				"rimraf": {
-					"version": "2.7.1",
-					"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-					"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-					"dev": true,
-					"requires": {
-						"glob": "^7.1.3"
-					}
-				}
-			}
-		},
-		"function-bind": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-			"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-			"dev": true
-		},
-		"get-intrinsic": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
-			"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
-			"dev": true,
-			"requires": {
-				"function-bind": "^1.1.1",
-				"has": "^1.0.3",
-				"has-symbols": "^1.0.1"
-			}
-		},
-		"glob": {
-			"version": "7.1.7",
-			"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
-			"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
-			"dev": true,
-			"requires": {
-				"fs.realpath": "^1.0.0",
-				"inflight": "^1.0.4",
-				"inherits": "2",
-				"minimatch": "^3.0.4",
-				"once": "^1.3.0",
-				"path-is-absolute": "^1.0.0"
-			}
-		},
-		"glob-parent": {
-			"version": "5.1.2",
-			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-			"requires": {
-				"is-glob": "^4.0.1"
-			}
-		},
-		"graceful-fs": {
-			"version": "4.2.6",
-			"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-			"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
-			"dev": true
-		},
-		"has": {
-			"version": "1.0.3",
-			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-			"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-			"dev": true,
-			"requires": {
-				"function-bind": "^1.1.1"
-			}
-		},
-		"has-flag": {
-			"version": "3.0.0",
-			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-			"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-			"dev": true
-		},
-		"has-symbols": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
-			"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
-			"dev": true
-		},
-		"htmlparser2": {
-			"version": "6.1.0",
-			"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
-			"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
-			"dev": true,
-			"requires": {
-				"domelementtype": "^2.0.1",
-				"domhandler": "^4.0.0",
-				"domutils": "^2.5.2",
-				"entities": "^2.0.0"
-			}
-		},
-		"http-proxy-agent": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
-			"integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
-			"dev": true,
-			"requires": {
-				"@tootallnate/once": "1",
-				"agent-base": "6",
-				"debug": "4"
-			}
-		},
-		"https-proxy-agent": {
-			"version": "5.0.0",
-			"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
-			"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
-			"dev": true,
-			"requires": {
-				"agent-base": "6",
-				"debug": "4"
-			}
-		},
-		"inflight": {
-			"version": "1.0.6",
-			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-			"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-			"dev": true,
-			"requires": {
-				"once": "^1.3.0",
-				"wrappy": "1"
-			}
-		},
-		"inherits": {
-			"version": "2.0.4",
-			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-			"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-			"dev": true
-		},
-		"is-binary-path": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-			"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-			"requires": {
-				"binary-extensions": "^2.0.0"
-			}
-		},
-		"is-core-module": {
-			"version": "2.5.0",
-			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz",
-			"integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==",
-			"dev": true,
-			"requires": {
-				"has": "^1.0.3"
-			}
-		},
-		"is-extglob": {
-			"version": "2.1.1",
-			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-			"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
-		},
-		"is-glob": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
-			"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
-			"requires": {
-				"is-extglob": "^2.1.1"
-			}
-		},
-		"is-number": {
-			"version": "7.0.0",
-			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
-		},
-		"isarray": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-			"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-			"dev": true
-		},
-		"js-tokens": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-			"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-			"dev": true
-		},
-		"js-yaml": {
-			"version": "3.14.1",
-			"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
-			"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
-			"dev": true,
-			"requires": {
-				"argparse": "^1.0.7",
-				"esprima": "^4.0.0"
-			}
-		},
-		"leven": {
-			"version": "3.1.0",
-			"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
-			"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
-			"dev": true
-		},
-		"linkify-it": {
-			"version": "2.2.0",
-			"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
-			"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
-			"dev": true,
-			"requires": {
-				"uc.micro": "^1.0.1"
-			}
-		},
-		"listenercount": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
-			"integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=",
-			"dev": true
-		},
-		"lodash": {
-			"version": "4.17.21",
-			"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-			"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
-			"dev": true
-		},
-		"markdown-it": {
-			"version": "10.0.0",
-			"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
-			"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
-			"dev": true,
-			"requires": {
-				"argparse": "^1.0.7",
-				"entities": "~2.0.0",
-				"linkify-it": "^2.0.0",
-				"mdurl": "^1.0.1",
-				"uc.micro": "^1.0.5"
-			},
-			"dependencies": {
-				"entities": {
-					"version": "2.0.3",
-					"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
-					"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
-					"dev": true
-				}
-			}
-		},
-		"mdurl": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
-			"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
-			"dev": true
-		},
-		"mime": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-			"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-			"dev": true
-		},
-		"minimatch": {
-			"version": "3.0.4",
-			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-			"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-			"dev": true,
-			"requires": {
-				"brace-expansion": "^1.1.7"
-			}
-		},
-		"minimist": {
-			"version": "1.2.5",
-			"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-			"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-			"dev": true
-		},
-		"mkdirp": {
-			"version": "0.5.5",
-			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-			"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-			"dev": true,
-			"requires": {
-				"minimist": "^1.2.5"
-			}
-		},
-		"ms": {
-			"version": "2.1.2",
-			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-			"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-			"dev": true
-		},
-		"mute-stream": {
-			"version": "0.0.8",
-			"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
-			"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-			"dev": true
-		},
-		"normalize-path": {
-			"version": "3.0.0",
-			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
-		},
-		"nth-check": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
-			"integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
-			"dev": true,
-			"requires": {
-				"boolbase": "^1.0.0"
-			}
-		},
-		"object-inspect": {
-			"version": "1.11.0",
-			"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
-			"integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
-			"dev": true
-		},
-		"once": {
-			"version": "1.4.0",
-			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-			"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-			"dev": true,
-			"requires": {
-				"wrappy": "1"
-			}
-		},
-		"os-homedir": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-			"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-			"dev": true
-		},
-		"os-tmpdir": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-			"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-			"dev": true
-		},
-		"osenv": {
-			"version": "0.1.5",
-			"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
-			"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
-			"dev": true,
-			"requires": {
-				"os-homedir": "^1.0.0",
-				"os-tmpdir": "^1.0.0"
-			}
-		},
-		"parse-semver": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
-			"integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=",
-			"dev": true,
-			"requires": {
-				"semver": "^5.1.0"
-			}
-		},
-		"parse5": {
-			"version": "6.0.1",
-			"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-			"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
-			"dev": true
-		},
-		"parse5-htmlparser2-tree-adapter": {
-			"version": "6.0.1",
-			"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
-			"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
-			"dev": true,
-			"requires": {
-				"parse5": "^6.0.1"
-			}
-		},
-		"path-is-absolute": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-			"dev": true
-		},
-		"path-parse": {
-			"version": "1.0.7",
-			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-			"dev": true
-		},
-		"pend": {
-			"version": "1.2.0",
-			"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-			"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
-			"dev": true
-		},
-		"picomatch": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
-			"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw=="
-		},
-		"process-nextick-args": {
-			"version": "2.0.1",
-			"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
-			"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-			"dev": true
-		},
-		"qs": {
-			"version": "6.10.1",
-			"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
-			"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
-			"dev": true,
-			"requires": {
-				"side-channel": "^1.0.4"
-			}
-		},
-		"read": {
-			"version": "1.0.7",
-			"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
-			"integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
-			"dev": true,
-			"requires": {
-				"mute-stream": "~0.0.4"
-			}
-		},
-		"readable-stream": {
-			"version": "2.3.7",
-			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-			"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-			"dev": true,
-			"requires": {
-				"core-util-is": "~1.0.0",
-				"inherits": "~2.0.3",
-				"isarray": "~1.0.0",
-				"process-nextick-args": "~2.0.0",
-				"safe-buffer": "~5.1.1",
-				"string_decoder": "~1.1.1",
-				"util-deprecate": "~1.0.1"
-			}
-		},
-		"readdirp": {
-			"version": "3.6.0",
-			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-			"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-			"requires": {
-				"picomatch": "^2.2.1"
-			}
-		},
-		"resolve": {
-			"version": "1.20.0",
-			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
-			"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
-			"dev": true,
-			"requires": {
-				"is-core-module": "^2.2.0",
-				"path-parse": "^1.0.6"
-			}
-		},
-		"rimraf": {
-			"version": "3.0.2",
-			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-			"dev": true,
-			"requires": {
-				"glob": "^7.1.3"
-			}
-		},
-		"safe-buffer": {
-			"version": "5.1.2",
-			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-			"dev": true
-		},
-		"semver": {
-			"version": "5.7.1",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-			"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
-		},
-		"setimmediate": {
-			"version": "1.0.5",
-			"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-			"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
-			"dev": true
-		},
-		"side-channel": {
-			"version": "1.0.4",
-			"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-			"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-			"dev": true,
-			"requires": {
-				"call-bind": "^1.0.0",
-				"get-intrinsic": "^1.0.2",
-				"object-inspect": "^1.9.0"
-			}
-		},
-		"sprintf-js": {
-			"version": "1.0.3",
-			"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-			"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
-			"dev": true
-		},
-		"string_decoder": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-			"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-			"dev": true,
-			"requires": {
-				"safe-buffer": "~5.1.0"
-			}
-		},
-		"supports-color": {
-			"version": "5.5.0",
-			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-			"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-			"dev": true,
-			"requires": {
-				"has-flag": "^3.0.0"
-			}
-		},
-		"tmp": {
-			"version": "0.2.1",
-			"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
-			"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
-			"dev": true,
-			"requires": {
-				"rimraf": "^3.0.0"
-			}
-		},
-		"to-regex-range": {
-			"version": "5.0.1",
-			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-			"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-			"requires": {
-				"is-number": "^7.0.0"
-			}
-		},
-		"traverse": {
-			"version": "0.3.9",
-			"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
-			"integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=",
-			"dev": true
-		},
-		"tslib": {
-			"version": "1.14.1",
-			"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-			"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-			"dev": true
-		},
-		"tslint": {
-			"version": "5.20.1",
-			"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
-			"integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==",
-			"dev": true,
-			"requires": {
-				"@babel/code-frame": "^7.0.0",
-				"builtin-modules": "^1.1.1",
-				"chalk": "^2.3.0",
-				"commander": "^2.12.1",
-				"
diff ": "^4.0.1",
-				"glob": "^7.1.1",
-				"js-yaml": "^3.13.1",
-				"minimatch": "^3.0.4",
-				"mkdirp": "^0.5.1",
-				"resolve": "^1.3.2",
-				"semver": "^5.3.0",
-				"tslib": "^1.8.0",
-				"tsutils": "^2.29.0"
-			}
-		},
-		"tsutils": {
-			"version": "2.29.0",
-			"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
-			"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
-			"dev": true,
-			"requires": {
-				"tslib": "^1.8.1"
-			}
-		},
-		"tunnel": {
-			"version": "0.0.6",
-			"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
-			"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
-			"dev": true
-		},
-		"typed-rest-client": {
-			"version": "1.8.4",
-			"resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz",
-			"integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==",
-			"dev": true,
-			"requires": {
-				"qs": "^6.9.1",
-				"tunnel": "0.0.6",
-				"underscore": "^1.12.1"
-			}
-		},
-		"typescript": {
-			"version": "3.9.10",
-			"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
-			"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
-			"dev": true
-		},
-		"uc.micro": {
-			"version": "1.0.6",
-			"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
-			"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
-			"dev": true
-		},
-		"underscore": {
-			"version": "1.13.1",
-			"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
-			"integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
-			"dev": true
-		},
-		"unzipper": {
-			"version": "0.10.11",
-			"resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz",
-			"integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==",
-			"dev": true,
-			"requires": {
-				"big-integer": "^1.6.17",
-				"binary": "~0.3.0",
-				"bluebird": "~3.4.1",
-				"buffer-indexof-polyfill": "~1.0.0",
-				"duplexer2": "~0.1.4",
-				"fstream": "^1.0.12",
-				"graceful-fs": "^4.2.2",
-				"listenercount": "~1.0.1",
-				"readable-stream": "~2.3.6",
-				"setimmediate": "~1.0.4"
-			}
-		},
-		"url-join": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
-			"integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=",
-			"dev": true
-		},
-		"util-deprecate": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-			"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-			"dev": true
-		},
-		"vsce": {
-			"version": "1.96.1",
-			"resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz",
-			"integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==",
-			"dev": true,
-			"requires": {
-				"azure-devops-node-api": "^11.0.1",
-				"chalk": "^2.4.2",
-				"cheerio": "^1.0.0-rc.9",
-				"commander": "^6.1.0",
-				"denodeify": "^1.2.1",
-				"glob": "^7.0.6",
-				"leven": "^3.1.0",
-				"lodash": "^4.17.15",
-				"markdown-it": "^10.0.0",
-				"mime": "^1.3.4",
-				"minimatch": "^3.0.3",
-				"osenv": "^0.1.3",
-				"parse-semver": "^1.1.1",
-				"read": "^1.0.7",
-				"semver": "^5.1.0",
-				"tmp": "^0.2.1",
-				"typed-rest-client": "^1.8.4",
-				"url-join": "^1.1.0",
-				"yauzl": "^2.3.1",
-				"yazl": "^2.2.2"
-			},
-			"dependencies": {
-				"commander": {
-					"version": "6.2.1",
-					"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
-					"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
-					"dev": true
-				}
-			}
-		},
-		"vscode-jsonrpc": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz",
-			"integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg=="
-		},
-		"vscode-languageclient": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz",
-			"integrity": "sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q==",
-			"requires": {
-				"semver": "^5.5.0",
-				"vscode-languageserver-protocol": "3.14.1"
-			}
-		},
-		"vscode-languageserver-protocol": {
-			"version": "3.14.1",
-			"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz",
-			"integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==",
-			"requires": {
-				"vscode-jsonrpc": "^4.0.0",
-				"vscode-languageserver-types": "3.14.0"
-			},
-			"dependencies": {
-				"vscode-languageserver-types": {
-					"version": "3.14.0",
-					"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
-					"integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A=="
-				}
-			}
-		},
-		"vscode-languageserver-types": {
-			"version": "3.16.0",
-			"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
-			"integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA=="
-		},
-		"vscode-test": {
-			"version": "1.6.1",
-			"resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz",
-			"integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==",
-			"dev": true,
-			"requires": {
-				"http-proxy-agent": "^4.0.1",
-				"https-proxy-agent": "^5.0.0",
-				"rimraf": "^3.0.2",
-				"unzipper": "^0.10.11"
-			}
-		},
-		"wrappy": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-			"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-			"dev": true
-		},
-		"yauzl": {
-			"version": "2.10.0",
-			"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
-			"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
-			"dev": true,
-			"requires": {
-				"buffer-crc32": "~0.2.3",
-				"fd-slicer": "~1.1.0"
-			}
-		},
-		"yazl": {
-			"version": "2.5.1",
-			"resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
-			"integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
-			"dev": true,
-			"requires": {
-				"buffer-crc32": "~0.2.3"
-			}
-		}
-	}
+  "name": "vscode-mlir",
+  "version": "0.0.4",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "vscode-mlir",
+      "version": "0.0.4",
+      "dependencies": {
+        "chokidar": "3.5.2",
+        "vscode-languageclient": "^5.2.1",
+        "vscode-languageserver-types": "3.16.0"
+      },
+      "devDependencies": {
+        "@types/mocha": "^5.2.0",
+        "@types/node": "^8.0.0",
+        "@types/vscode": "1.52.*",
+        "clang-format": "1.4.0",
+        "tslint": "^5.16.0",
+        "typescript": "^3.5.1",
+        "vsce": "^1.75.0",
+        "vscode-test": "^1.3.0"
+      },
+      "engines": {
+        "vscode": "^1.52.0"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
+      "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/highlight": "^7.14.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.14.8",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz",
+      "integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+      "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.14.5",
+        "chalk": "^2.0.0",
+        "js-tokens": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@tootallnate/once": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+      "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/@types/mocha": {
+      "version": "5.2.7",
+      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
+      "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
+      "dev": true
+    },
+    "node_modules/@types/node": {
+      "version": "8.10.66",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz",
+      "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==",
+      "dev": true
+    },
+    "node_modules/@types/vscode": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.52.0.tgz",
+      "integrity": "sha512-Kt3bvWzAvvF/WH9YEcrCICDp0Z7aHhJGhLJ1BxeyNP6yRjonWqWnAIh35/pXAjswAnWOABrYlF7SwXR9+1nnLA==",
+      "dev": true
+    },
+    "node_modules/agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "dev": true,
+      "dependencies": {
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "node_modules/async": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+      "dev": true
+    },
+    "node_modules/azure-devops-node-api": {
+      "version": "11.0.1",
+      "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz",
+      "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==",
+      "dev": true,
+      "dependencies": {
+        "tunnel": "0.0.6",
+        "typed-rest-client": "^1.8.4"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "node_modules/big-integer": {
+      "version": "1.6.48",
+      "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
+      "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/binary": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
+      "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=",
+      "dev": true,
+      "dependencies": {
+        "buffers": "~0.1.1",
+        "chainsaw": "~0.1.0"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/bluebird": {
+      "version": "3.4.7",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
+      "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=",
+      "dev": true
+    },
+    "node_modules/boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+      "dev": true
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dependencies": {
+        "fill-range": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/buffer-crc32": {
+      "version": "0.2.13",
+      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+      "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/buffer-indexof-polyfill": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
+      "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/buffers": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
+      "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=",
+      "dev": true,
+      "engines": {
+        "node": ">=0.2.0"
+      }
+    },
+    "node_modules/builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/call-bind": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/chainsaw": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
+      "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=",
+      "dev": true,
+      "dependencies": {
+        "traverse": ">=0.3.0 <0.4"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/cheerio": {
+      "version": "1.0.0-rc.10",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
+      "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
+      "dev": true,
+      "dependencies": {
+        "cheerio-select": "^1.5.0",
+        "dom-serializer": "^1.3.2",
+        "domhandler": "^4.2.0",
+        "htmlparser2": "^6.1.0",
+        "parse5": "^6.0.1",
+        "parse5-htmlparser2-tree-adapter": "^6.0.1",
+        "tslib": "^2.2.0"
+      },
+      "engines": {
+        "node": ">= 6"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
+      "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
+      "dev": true,
+      "dependencies": {
+        "css-select": "^4.1.3",
+        "css-what": "^5.0.1",
+        "domelementtype": "^2.2.0",
+        "domhandler": "^4.2.0",
+        "domutils": "^2.7.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cheerio/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+      "dev": true
+    },
+    "node_modules/chokidar": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
+      "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/clang-format": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.4.0.tgz",
+      "integrity": "sha512-NrdyUnHJOGvMa60vbWk7GJTvOdhibj3uK5C0FlwdNG4301OUvqEJTFce9I9x8qw2odBbIVrJ+9xbsFS3a4FbDA==",
+      "dev": true,
+      "dependencies": {
+        "async": "^1.5.2",
+        "glob": "^7.0.0",
+        "resolve": "^1.1.6"
+      },
+      "bin": {
+        "check-clang-format": "bin/check-clang-format.js",
+        "clang-format": "index.js",
+        "git-clang-format": "bin/git-clang-format"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "node_modules/core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "node_modules/css-select": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
+      "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
+      "dev": true,
+      "dependencies": {
+        "boolbase": "^1.0.0",
+        "css-what": "^5.0.0",
+        "domhandler": "^4.2.0",
+        "domutils": "^2.6.0",
+        "nth-check": "^2.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/css-what": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
+      "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/debug": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+      "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/denodeify": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
+      "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=",
+      "dev": true
+    },
+    "node_modules/
diff ": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/
diff /-/
diff -4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/dom-serializer": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+      "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+      "dev": true,
+      "dependencies": {
+        "domelementtype": "^2.0.1",
+        "domhandler": "^4.2.0",
+        "entities": "^2.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+      }
+    },
+    "node_modules/domelementtype": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+      "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ]
+    },
+    "node_modules/domhandler": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
+      "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
+      "dev": true,
+      "dependencies": {
+        "domelementtype": "^2.2.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/domutils": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
+      "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
+      "dev": true,
+      "dependencies": {
+        "dom-serializer": "^1.0.1",
+        "domelementtype": "^2.2.0",
+        "domhandler": "^4.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domutils?sponsor=1"
+      }
+    },
+    "node_modules/duplexer2": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+      "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
+      "dev": true,
+      "dependencies": {
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "node_modules/entities": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+      "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true,
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/fd-slicer": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+      "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+      "dev": true,
+      "dependencies": {
+        "pend": "~1.2.0"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      },
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/fstream/node_modules/rimraf": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "dev": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+      "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "has-symbols": "^1.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.1.7",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "dev": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.6",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+      "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
+      "dev": true
+    },
+    "node_modules/has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+      "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/htmlparser2": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
+      "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
+      "dev": true,
+      "funding": [
+        "https://github.com/fb55/htmlparser2?sponsor=1",
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "dependencies": {
+        "domelementtype": "^2.0.1",
+        "domhandler": "^4.0.0",
+        "domutils": "^2.5.2",
+        "entities": "^2.0.0"
+      }
+    },
+    "node_modules/http-proxy-agent": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+      "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+      "dev": true,
+      "dependencies": {
+        "@tootallnate/once": "1",
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
+      "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
+      "dev": true,
+      "dependencies": {
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz",
+      "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==",
+      "dev": true,
+      "dependencies": {
+        "has": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "node_modules/js-yaml": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/leven": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+      "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/linkify-it": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
+      "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
+      "dev": true,
+      "dependencies": {
+        "uc.micro": "^1.0.1"
+      }
+    },
+    "node_modules/listenercount": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
+      "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=",
+      "dev": true
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "dev": true
+    },
+    "node_modules/markdown-it": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+      "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "entities": "~2.0.0",
+        "linkify-it": "^2.0.0",
+        "mdurl": "^1.0.1",
+        "uc.micro": "^1.0.5"
+      },
+      "bin": {
+        "markdown-it": "bin/markdown-it.js"
+      }
+    },
+    "node_modules/markdown-it/node_modules/entities": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
+      "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
+      "dev": true
+    },
+    "node_modules/mdurl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
+      "dev": true
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+      "dev": true
+    },
+    "node_modules/mkdirp": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+      "dev": true,
+      "dependencies": {
+        "minimist": "^1.2.5"
+      },
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/mute-stream": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+      "dev": true
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/nth-check": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
+      "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
+      "dev": true,
+      "dependencies": {
+        "boolbase": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/nth-check?sponsor=1"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
+      "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "dev": true,
+      "dependencies": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.0.0"
+      }
+    },
+    "node_modules/parse-semver": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
+      "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=",
+      "dev": true,
+      "dependencies": {
+        "semver": "^5.1.0"
+      }
+    },
+    "node_modules/parse5": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
+      "dev": true
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
+      "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
+      "dev": true,
+      "dependencies": {
+        "parse5": "^6.0.1"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/pend": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+      "dev": true
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+      "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "node_modules/qs": {
+      "version": "6.10.1",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
+      "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
+      "dev": true,
+      "dependencies": {
+        "side-channel": "^1.0.4"
+      },
+      "engines": {
+        "node": ">=0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/read": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
+      "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
+      "dev": true,
+      "dependencies": {
+        "mute-stream": "~0.0.4"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+      "dev": true,
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.2.0",
+        "path-parse": "^1.0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "dev": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "node_modules/semver": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+      "dev": true
+    },
+    "node_modules/side-channel": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
+    "node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tmp": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+      "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+      "dev": true,
+      "dependencies": {
+        "rimraf": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8.17.0"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/traverse": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
+      "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "dev": true
+    },
+    "node_modules/tslint": {
+      "version": "5.20.1",
+      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
+      "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.0.0",
+        "builtin-modules": "^1.1.1",
+        "chalk": "^2.3.0",
+        "commander": "^2.12.1",
+        "
diff ": "^4.0.1",
+        "glob": "^7.1.1",
+        "js-yaml": "^3.13.1",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "resolve": "^1.3.2",
+        "semver": "^5.3.0",
+        "tslib": "^1.8.0",
+        "tsutils": "^2.29.0"
+      },
+      "bin": {
+        "tslint": "bin/tslint"
+      },
+      "engines": {
+        "node": ">=4.8.0"
+      },
+      "peerDependencies": {
+        "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev"
+      }
+    },
+    "node_modules/tsutils": {
+      "version": "2.29.0",
+      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+      "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^1.8.1"
+      },
+      "peerDependencies": {
+        "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
+      }
+    },
+    "node_modules/tunnel": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+      "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
+      }
+    },
+    "node_modules/typed-rest-client": {
+      "version": "1.8.4",
+      "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz",
+      "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==",
+      "dev": true,
+      "dependencies": {
+        "qs": "^6.9.1",
+        "tunnel": "0.0.6",
+        "underscore": "^1.12.1"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "3.9.10",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
+      "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    },
+    "node_modules/uc.micro": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+      "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+      "dev": true
+    },
+    "node_modules/underscore": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
+      "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
+      "dev": true
+    },
+    "node_modules/unzipper": {
+      "version": "0.10.11",
+      "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz",
+      "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==",
+      "dev": true,
+      "dependencies": {
+        "big-integer": "^1.6.17",
+        "binary": "~0.3.0",
+        "bluebird": "~3.4.1",
+        "buffer-indexof-polyfill": "~1.0.0",
+        "duplexer2": "~0.1.4",
+        "fstream": "^1.0.12",
+        "graceful-fs": "^4.2.2",
+        "listenercount": "~1.0.1",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "~1.0.4"
+      }
+    },
+    "node_modules/url-join": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
+      "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=",
+      "dev": true
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "node_modules/vsce": {
+      "version": "1.96.1",
+      "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz",
+      "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==",
+      "dev": true,
+      "dependencies": {
+        "azure-devops-node-api": "^11.0.1",
+        "chalk": "^2.4.2",
+        "cheerio": "^1.0.0-rc.9",
+        "commander": "^6.1.0",
+        "denodeify": "^1.2.1",
+        "glob": "^7.0.6",
+        "leven": "^3.1.0",
+        "lodash": "^4.17.15",
+        "markdown-it": "^10.0.0",
+        "mime": "^1.3.4",
+        "minimatch": "^3.0.3",
+        "osenv": "^0.1.3",
+        "parse-semver": "^1.1.1",
+        "read": "^1.0.7",
+        "semver": "^5.1.0",
+        "tmp": "^0.2.1",
+        "typed-rest-client": "^1.8.4",
+        "url-join": "^1.1.0",
+        "yauzl": "^2.3.1",
+        "yazl": "^2.2.2"
+      },
+      "bin": {
+        "vsce": "out/vsce"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/vsce/node_modules/commander": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+      "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/vscode-jsonrpc": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz",
+      "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==",
+      "engines": {
+        "node": ">=8.0.0 || >=10.0.0"
+      }
+    },
+    "node_modules/vscode-languageclient": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz",
+      "integrity": "sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q==",
+      "dependencies": {
+        "semver": "^5.5.0",
+        "vscode-languageserver-protocol": "3.14.1"
+      },
+      "engines": {
+        "vscode": "^1.30"
+      }
+    },
+    "node_modules/vscode-languageserver-protocol": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz",
+      "integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==",
+      "dependencies": {
+        "vscode-jsonrpc": "^4.0.0",
+        "vscode-languageserver-types": "3.14.0"
+      }
+    },
+    "node_modules/vscode-languageserver-protocol/node_modules/vscode-languageserver-types": {
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
+      "integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A=="
+    },
+    "node_modules/vscode-languageserver-types": {
+      "version": "3.16.0",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
+      "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA=="
+    },
+    "node_modules/vscode-test": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz",
+      "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==",
+      "deprecated": "This package has been renamed to @vscode/test-electron, please update to the new name",
+      "dev": true,
+      "dependencies": {
+        "http-proxy-agent": "^4.0.1",
+        "https-proxy-agent": "^5.0.0",
+        "rimraf": "^3.0.2",
+        "unzipper": "^0.10.11"
+      },
+      "engines": {
+        "node": ">=8.9.3"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "node_modules/yauzl": {
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+      "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+      "dev": true,
+      "dependencies": {
+        "buffer-crc32": "~0.2.3",
+        "fd-slicer": "~1.1.0"
+      }
+    },
+    "node_modules/yazl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
+      "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
+      "dev": true,
+      "dependencies": {
+        "buffer-crc32": "~0.2.3"
+      }
+    }
+  },
+  "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
+      "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.14.5"
+      }
+    },
+    "@babel/helper-validator-identifier": {
+      "version": "7.14.8",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz",
+      "integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==",
+      "dev": true
+    },
+    "@babel/highlight": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+      "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.14.5",
+        "chalk": "^2.0.0",
+        "js-tokens": "^4.0.0"
+      }
+    },
+    "@tootallnate/once": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+      "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+      "dev": true
+    },
+    "@types/mocha": {
+      "version": "5.2.7",
+      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
+      "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
+      "dev": true
+    },
+    "@types/node": {
+      "version": "8.10.66",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz",
+      "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==",
+      "dev": true
+    },
+    "@types/vscode": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.52.0.tgz",
+      "integrity": "sha512-Kt3bvWzAvvF/WH9YEcrCICDp0Z7aHhJGhLJ1BxeyNP6yRjonWqWnAIh35/pXAjswAnWOABrYlF7SwXR9+1nnLA==",
+      "dev": true
+    },
+    "agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "dev": true,
+      "requires": {
+        "debug": "4"
+      }
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "anymatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "async": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+      "dev": true
+    },
+    "azure-devops-node-api": {
+      "version": "11.0.1",
+      "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz",
+      "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==",
+      "dev": true,
+      "requires": {
+        "tunnel": "0.0.6",
+        "typed-rest-client": "^1.8.4"
+      }
+    },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "big-integer": {
+      "version": "1.6.48",
+      "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
+      "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
+      "dev": true
+    },
+    "binary": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
+      "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=",
+      "dev": true,
+      "requires": {
+        "buffers": "~0.1.1",
+        "chainsaw": "~0.1.0"
+      }
+    },
+    "binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
+    },
+    "bluebird": {
+      "version": "3.4.7",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
+      "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=",
+      "dev": true
+    },
+    "boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+      "dev": true
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "requires": {
+        "fill-range": "^7.0.1"
+      }
+    },
+    "buffer-crc32": {
+      "version": "0.2.13",
+      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+      "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+      "dev": true
+    },
+    "buffer-indexof-polyfill": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
+      "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
+      "dev": true
+    },
+    "buffers": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
+      "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=",
+      "dev": true
+    },
+    "builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true
+    },
+    "call-bind": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.0.2"
+      }
+    },
+    "chainsaw": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
+      "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=",
+      "dev": true,
+      "requires": {
+        "traverse": ">=0.3.0 <0.4"
+      }
+    },
+    "chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "cheerio": {
+      "version": "1.0.0-rc.10",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
+      "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
+      "dev": true,
+      "requires": {
+        "cheerio-select": "^1.5.0",
+        "dom-serializer": "^1.3.2",
+        "domhandler": "^4.2.0",
+        "htmlparser2": "^6.1.0",
+        "parse5": "^6.0.1",
+        "parse5-htmlparser2-tree-adapter": "^6.0.1",
+        "tslib": "^2.2.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+          "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+          "dev": true
+        }
+      }
+    },
+    "cheerio-select": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
+      "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
+      "dev": true,
+      "requires": {
+        "css-select": "^4.1.3",
+        "css-what": "^5.0.1",
+        "domelementtype": "^2.2.0",
+        "domhandler": "^4.2.0",
+        "domutils": "^2.7.0"
+      }
+    },
+    "chokidar": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
+      "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+      "requires": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "fsevents": "~2.3.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      }
+    },
+    "clang-format": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.4.0.tgz",
+      "integrity": "sha512-NrdyUnHJOGvMa60vbWk7GJTvOdhibj3uK5C0FlwdNG4301OUvqEJTFce9I9x8qw2odBbIVrJ+9xbsFS3a4FbDA==",
+      "dev": true,
+      "requires": {
+        "async": "^1.5.2",
+        "glob": "^7.0.0",
+        "resolve": "^1.1.6"
+      }
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "css-select": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
+      "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
+      "dev": true,
+      "requires": {
+        "boolbase": "^1.0.0",
+        "css-what": "^5.0.0",
+        "domhandler": "^4.2.0",
+        "domutils": "^2.6.0",
+        "nth-check": "^2.0.0"
+      }
+    },
+    "css-what": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
+      "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
+      "dev": true
+    },
+    "debug": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+      "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+      "dev": true,
+      "requires": {
+        "ms": "2.1.2"
+      }
+    },
+    "denodeify": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
+      "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=",
+      "dev": true
+    },
+    "
diff ": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/
diff /-/
diff -4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "dev": true
+    },
+    "dom-serializer": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+      "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "^2.0.1",
+        "domhandler": "^4.2.0",
+        "entities": "^2.0.0"
+      }
+    },
+    "domelementtype": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+      "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+      "dev": true
+    },
+    "domhandler": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
+      "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "^2.2.0"
+      }
+    },
+    "domutils": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
+      "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
+      "dev": true,
+      "requires": {
+        "dom-serializer": "^1.0.1",
+        "domelementtype": "^2.2.0",
+        "domhandler": "^4.2.0"
+      }
+    },
+    "duplexer2": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+      "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "entities": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+      "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true
+    },
+    "fd-slicer": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+      "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+      "dev": true,
+      "requires": {
+        "pend": "~1.2.0"
+      }
+    },
+    "fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "optional": true
+    },
+    "fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      },
+      "dependencies": {
+        "rimraf": {
+          "version": "2.7.1",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        }
+      }
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "get-intrinsic": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+      "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "has-symbols": "^1.0.1"
+      }
+    },
+    "glob": {
+      "version": "7.1.7",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.6",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+      "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
+      "dev": true
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
+    },
+    "has-symbols": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+      "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
+      "dev": true
+    },
+    "htmlparser2": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
+      "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "^2.0.1",
+        "domhandler": "^4.0.0",
+        "domutils": "^2.5.2",
+        "entities": "^2.0.0"
+      }
+    },
+    "http-proxy-agent": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+      "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+      "dev": true,
+      "requires": {
+        "@tootallnate/once": "1",
+        "agent-base": "6",
+        "debug": "4"
+      }
+    },
+    "https-proxy-agent": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
+      "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
+      "dev": true,
+      "requires": {
+        "agent-base": "6",
+        "debug": "4"
+      }
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "requires": {
+        "binary-extensions": "^2.0.0"
+      }
+    },
+    "is-core-module": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz",
+      "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+    },
+    "is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      }
+    },
+    "leven": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+      "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+      "dev": true
+    },
+    "linkify-it": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
+      "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
+      "dev": true,
+      "requires": {
+        "uc.micro": "^1.0.1"
+      }
+    },
+    "listenercount": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
+      "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=",
+      "dev": true
+    },
+    "lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "dev": true
+    },
+    "markdown-it": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+      "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "entities": "~2.0.0",
+        "linkify-it": "^2.0.0",
+        "mdurl": "^1.0.1",
+        "uc.micro": "^1.0.5"
+      },
+      "dependencies": {
+        "entities": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
+          "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
+          "dev": true
+        }
+      }
+    },
+    "mdurl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
+      "dev": true
+    },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+      "dev": true
+    },
+    "mkdirp": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.5"
+      }
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "mute-stream": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+      "dev": true
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+    },
+    "nth-check": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
+      "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
+      "dev": true,
+      "requires": {
+        "boolbase": "^1.0.0"
+      }
+    },
+    "object-inspect": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
+      "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
+      "dev": true
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+      "dev": true
+    },
+    "osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "dev": true,
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.0.0"
+      }
+    },
+    "parse-semver": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
+      "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=",
+      "dev": true,
+      "requires": {
+        "semver": "^5.1.0"
+      }
+    },
+    "parse5": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
+      "dev": true
+    },
+    "parse5-htmlparser2-tree-adapter": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
+      "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
+      "dev": true,
+      "requires": {
+        "parse5": "^6.0.1"
+      }
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "pend": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+      "dev": true
+    },
+    "picomatch": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+      "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw=="
+    },
+    "process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "qs": {
+      "version": "6.10.1",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
+      "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
+      "dev": true,
+      "requires": {
+        "side-channel": "^1.0.4"
+      }
+    },
+    "read": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
+      "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
+      "dev": true,
+      "requires": {
+        "mute-stream": "~0.0.4"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "requires": {
+        "picomatch": "^2.2.1"
+      }
+    },
+    "resolve": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+      "dev": true,
+      "requires": {
+        "is-core-module": "^2.2.0",
+        "path-parse": "^1.0.6"
+      }
+    },
+    "rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "semver": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+    },
+    "setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+      "dev": true
+    },
+    "side-channel": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
+      }
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "tmp": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+      "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+      "dev": true,
+      "requires": {
+        "rimraf": "^3.0.0"
+      }
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "traverse": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
+      "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=",
+      "dev": true
+    },
+    "tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "dev": true
+    },
+    "tslint": {
+      "version": "5.20.1",
+      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
+      "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "builtin-modules": "^1.1.1",
+        "chalk": "^2.3.0",
+        "commander": "^2.12.1",
+        "
diff ": "^4.0.1",
+        "glob": "^7.1.1",
+        "js-yaml": "^3.13.1",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "resolve": "^1.3.2",
+        "semver": "^5.3.0",
+        "tslib": "^1.8.0",
+        "tsutils": "^2.29.0"
+      }
+    },
+    "tsutils": {
+      "version": "2.29.0",
+      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+      "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.8.1"
+      }
+    },
+    "tunnel": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+      "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+      "dev": true
+    },
+    "typed-rest-client": {
+      "version": "1.8.4",
+      "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz",
+      "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==",
+      "dev": true,
+      "requires": {
+        "qs": "^6.9.1",
+        "tunnel": "0.0.6",
+        "underscore": "^1.12.1"
+      }
+    },
+    "typescript": {
+      "version": "3.9.10",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
+      "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
+      "dev": true
+    },
+    "uc.micro": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+      "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+      "dev": true
+    },
+    "underscore": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
+      "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
+      "dev": true
+    },
+    "unzipper": {
+      "version": "0.10.11",
+      "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz",
+      "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==",
+      "dev": true,
+      "requires": {
+        "big-integer": "^1.6.17",
+        "binary": "~0.3.0",
+        "bluebird": "~3.4.1",
+        "buffer-indexof-polyfill": "~1.0.0",
+        "duplexer2": "~0.1.4",
+        "fstream": "^1.0.12",
+        "graceful-fs": "^4.2.2",
+        "listenercount": "~1.0.1",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "~1.0.4"
+      }
+    },
+    "url-join": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
+      "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=",
+      "dev": true
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "vsce": {
+      "version": "1.96.1",
+      "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz",
+      "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==",
+      "dev": true,
+      "requires": {
+        "azure-devops-node-api": "^11.0.1",
+        "chalk": "^2.4.2",
+        "cheerio": "^1.0.0-rc.9",
+        "commander": "^6.1.0",
+        "denodeify": "^1.2.1",
+        "glob": "^7.0.6",
+        "leven": "^3.1.0",
+        "lodash": "^4.17.15",
+        "markdown-it": "^10.0.0",
+        "mime": "^1.3.4",
+        "minimatch": "^3.0.3",
+        "osenv": "^0.1.3",
+        "parse-semver": "^1.1.1",
+        "read": "^1.0.7",
+        "semver": "^5.1.0",
+        "tmp": "^0.2.1",
+        "typed-rest-client": "^1.8.4",
+        "url-join": "^1.1.0",
+        "yauzl": "^2.3.1",
+        "yazl": "^2.2.2"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+          "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+          "dev": true
+        }
+      }
+    },
+    "vscode-jsonrpc": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz",
+      "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg=="
+    },
+    "vscode-languageclient": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz",
+      "integrity": "sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q==",
+      "requires": {
+        "semver": "^5.5.0",
+        "vscode-languageserver-protocol": "3.14.1"
+      }
+    },
+    "vscode-languageserver-protocol": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz",
+      "integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==",
+      "requires": {
+        "vscode-jsonrpc": "^4.0.0",
+        "vscode-languageserver-types": "3.14.0"
+      },
+      "dependencies": {
+        "vscode-languageserver-types": {
+          "version": "3.14.0",
+          "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
+          "integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A=="
+        }
+      }
+    },
+    "vscode-languageserver-types": {
+      "version": "3.16.0",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
+      "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA=="
+    },
+    "vscode-test": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz",
+      "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==",
+      "dev": true,
+      "requires": {
+        "http-proxy-agent": "^4.0.1",
+        "https-proxy-agent": "^5.0.0",
+        "rimraf": "^3.0.2",
+        "unzipper": "^0.10.11"
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "yauzl": {
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+      "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+      "dev": true,
+      "requires": {
+        "buffer-crc32": "~0.2.3",
+        "fd-slicer": "~1.1.0"
+      }
+    },
+    "yazl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
+      "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
+      "dev": true,
+      "requires": {
+        "buffer-crc32": "~0.2.3"
+      }
+    }
+  }
 }

diff  --git a/mlir/utils/vscode/package.json b/mlir/utils/vscode/package.json
index e45ce4cd4ea5e..9747dd72a852b 100644
--- a/mlir/utils/vscode/package.json
+++ b/mlir/utils/vscode/package.json
@@ -14,10 +14,12 @@
   ],
   "keywords": [
     "LLVM",
-    "MLIR"
+    "MLIR",
+    "PDLL"
   ],
   "activationEvents": [
-    "onLanguage:mlir"
+    "onLanguage:mlir",
+    "onLanguage:pdll"
   ],
   "main": "./out/extension",
   "scripts": {
@@ -62,6 +64,17 @@
       },
       {
         "id": "mlir-injection"
+      },
+      {
+        "id": "pdll",
+        "aliases": [
+          "PDLL",
+          "pdll"
+        ],
+        "extensions": [
+          ".pdll"
+        ],
+        "configuration": "./pdll-language-configuration.json"
       }
     ],
     "grammars": [
@@ -90,6 +103,11 @@
         "embeddedLanguages": {
           "source.mlir": "mlir"
         }
+      },
+      {
+        "language": "pdll",
+        "scopeName": "source.pdll",
+        "path": "./pdll-grammar.json"
       }
     ],
     "configuration": {
@@ -101,6 +119,11 @@
           "type": "string",
           "description": "The file path of the mlir-lsp-server executable."
         },
+        "mlir.pdll_server_path": {
+          "scope": "resource",
+          "type": "string",
+          "description": "The file path of the mlir-pdll-lsp-server executable."
+        },
         "mlir.onSettingsChanged": {
           "type": "string",
           "default": "prompt",

diff  --git a/mlir/utils/vscode/pdll-grammar.json b/mlir/utils/vscode/pdll-grammar.json
new file mode 100644
index 0000000000000..142d3978906ab
--- /dev/null
+++ b/mlir/utils/vscode/pdll-grammar.json
@@ -0,0 +1,521 @@
+{
+  "name": "PDLL",
+  "fileTypes": [
+    "pdll"
+  ],
+  "patterns": [
+    {
+      "include": "#comment"
+    },
+    {
+      "include": "#string"
+    },
+    {
+      "include": "#string_block"
+    },
+    {
+      "include": "#integer"
+    },
+    {
+      "include": "#include"
+    },
+    {
+      "include": "#user_constraint"
+    },
+    {
+      "include": "#user_rewrite"
+    },
+    {
+      "include": "#pattern"
+    }
+  ],
+  "repository": {
+    "comment": {
+      "match": "\/\/.*$",
+      "name": "comment.line.double-slash.pdll"
+    },
+    "string": {
+      "name": "string.quoted.double.pdll",
+      "begin": "\"",
+      "end": "\"",
+      "beginCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.begin.pdll"
+        }
+      },
+      "patterns": [
+        {
+          "match": "\\\\[nt\"]",
+          "name": "constant.character.escape.pdll"
+        },
+        {
+          "match": "\\\\.",
+          "name": "invalid.illegal.pdll"
+        }
+      ],
+      "endCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.end.pdll"
+        }
+      }
+    },
+    "string_block": {
+      "name": "string.quoted.triple.pdll",
+      "begin": "\\[{",
+      "end": "}]",
+      "beginCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.begin.pdll"
+        }
+      },
+      "patterns": [
+        {
+          "match": "\\\\[nt\"]",
+          "name": "constant.character.escape.pdll"
+        },
+        {
+          "match": "\\\\.",
+          "name": "invalid.illegal.pdll"
+        }
+      ],
+      "endCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.end.pdll"
+        }
+      }
+    },
+    "integer": {
+      "match": "[0-9]+",
+      "name": "constant.numeric.pdll"
+    },
+    "include": {
+      "patterns": [
+        {
+          "match": "(#include)",
+          "name": "keyword.control.pdll"
+        }
+      ]
+    },
+    "argument_or_result_list": {
+      "patterns": [
+        {
+          "match": "\\b([aA-zZ_0-9]*)\\b\\s*:\\s*([aA-zZ_0-9]+)\\b(\\<([^\\>]+)\\>)?",
+          "captures": {
+            "1": {
+              "name": "variable.parameter.pdll"
+            },
+            "2": {
+              "name": "entity.name.type.pdll"
+            },
+            "4": {
+              "name": "variable.other.enummember.pdll"
+            }
+          }
+        },
+        {
+          "match": "(\\(|\\>|,)\\s*([aA-zZ_0-9]+)\\b(\\<([^\\>]+)\\>)?\\s*(?=[^:])",
+          "captures": {
+            "2": {
+              "name": "entity.name.type.pdll"
+            },
+            "4": {
+              "name": "variable.other.enummember.pdll"
+            }
+          }
+        }
+      ]
+    },
+    "user_constraint": {
+      "patterns": [
+        {
+          "begin": "\\b(Constraint)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.type.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "begin": "(\\[{)",
+              "patterns": [
+                {
+                  "include": "source.cpp"
+                }
+              ],
+              "end": "(}])"
+            },
+            {
+              "begin": "(?=\\()",
+              "patterns": [
+                {
+                  "include": "#argument_or_result_list"
+                }
+              ],
+              "end": "\\)"
+            },
+            {
+              "include": "#argument_or_result_list"
+            },
+            {
+              "begin": "{",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=})"
+            },
+            {
+              "begin": "=>",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=;|,|\\))"
+            }
+          ],
+          "end": "(}|;|,)|(?=\\))"
+        }
+      ]
+    },
+    "user_rewrite": {
+      "patterns": [
+        {
+          "begin": "\\b(Rewrite)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.function.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "begin": "(\\[{)",
+              "patterns": [
+                {
+                  "include": "source.cpp"
+                }
+              ],
+              "end": "(}])"
+            },
+            {
+              "begin": "(?=\\()",
+              "patterns": [
+                {
+                  "include": "#argument_or_result_list"
+                }
+              ],
+              "end": "\\)"
+            },
+            {
+              "include": "#argument_or_result_list"
+            },
+            {
+              "begin": "{",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=})"
+            },
+            {
+              "begin": "=>",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=;|,|\\))"
+            }
+          ],
+          "end": "(}|;|,)|(?=\\))"
+        }
+      ]
+    },
+    "pattern_metadata": {
+      "patterns": [
+        {
+          "match": "\\b(with)\\b",
+          "name": "keyword.other.pdll"
+        },
+        {
+          "match": "\\b(benefit)\\b\\(([0-9]+)\\)",
+          "captures": {
+            "1": {
+              "name": "entity.name.variable.pdll"
+            },
+            "2": {
+              "name": "constant.numeric.pdll"
+            }
+          }
+        },
+        {
+          "match": "\\b(recursion)\\b",
+          "name": "entity.name.variable.pdll"
+        }
+      ]
+    },
+    "pattern": {
+      "patterns": [
+        {
+          "begin": "\\b(Pattern)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?\\s*(\\bwith\\b\\s*[^\\{]*)?\\s*({)",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.function.pdll"
+            },
+            "3": {
+              "patterns": [
+                {
+                  "include": "#pattern_metadata"
+                }
+              ]
+            }
+          },
+          "patterns": [
+            {
+              "include": "#inside_pattern"
+            }
+          ],
+          "end": "(})"
+        },
+        {
+          "begin": "\\b(Pattern)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?\\s*(\\bwith\\b\\s*[^\\=]*)?\\s*(=>)",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.function.pdll"
+            },
+            "3": {
+              "patterns": [
+                {
+                  "include": "#pattern_metadata"
+                }
+              ]
+            }
+          },
+          "patterns": [
+            {
+              "include": "#inside_pattern"
+            }
+          ],
+          "end": ";"
+        }
+      ]
+    },
+    "inside_pattern": {
+      "patterns": [
+        {
+          "match": "\\b(erase|let|replace|return|rewrite|with)\\b",
+          "captures": {
+            "1": {
+              "name": "keyword.control.pdll"
+            }
+          }
+        },
+        {
+          "include": "#expressions"
+        }
+      ]
+    },
+    "variable_constraint": {
+      "patterns": [
+        {
+          "match": "\\b(Op)<([a-zA-Z0-9_\\.$-]*)>",
+          "captures": {
+            "1": {
+              "name": "entity.name.type.pdll"
+            },
+            "2": {
+              "name": "variable.other.enummember.pdll"
+            }
+          }
+        },
+        {
+          "begin": "<",
+          "patterns": [
+            {
+              "include": "#expressions"
+            }
+          ],
+          "end": ">"
+        },
+        {
+          "match": "[a-zA-Z_0-9]+",
+          "name": "entity.name.type.pdll"
+        }
+      ]
+    },
+    "variable_definition": {
+      "patterns": [
+        {
+          "begin": "\\b([aA-zZ_0-9]*)\\b\\s*:\\s*\\[",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.variable.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#variable_constraint"
+            }
+          ],
+          "end": "\\]"
+        },
+        {
+          "match": "\\b([aA-zZ_0-9]*)\\b\\s*:\\s*([aA-zZ_0-9]+(\\<([^\\>]+)\\>)?)",
+          "captures": {
+            "1": {
+              "name": "entity.name.variable.pdll"
+            },
+            "2": {
+              "patterns": [
+                {
+                  "include": "#variable_constraint"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "expressions": {
+      "patterns": [
+        {
+          "include": "#user_constraint"
+        },
+        {
+          "include": "#user_rewrite"
+        },
+        {
+          "include": "#attr_expr"
+        },
+        {
+          "include": "#op_expr"
+        },
+        {
+          "include": "#type_expr"
+        },
+        {
+          "include": "#call_expr"
+        },
+        {
+          "include": "#variable_definition"
+        },
+        {
+          "include": "#identifier_expr"
+        },
+        {
+          "include": "#string"
+        },
+        {
+          "include": "#string_block"
+        },
+        {
+          "include": "#comment"
+        },
+        {
+          "begin": "{",
+          "patterns": [
+            {
+              "include": "#inside_pattern"
+            }
+          ],
+          "end": "}"
+        },
+        {
+          "begin": "\\(",
+          "patterns": [
+            {
+              "include": "#expressions"
+            }
+          ],
+          "end": "\\)"
+        }
+      ]
+    },
+    "attr_expr": {
+      "patterns": [
+        {
+          "begin": "(attr)<",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#string"
+            },
+            {
+              "include": "#string_block"
+            }
+          ],
+          "end": ">"
+        }
+      ]
+    },
+    "call_expr": {
+      "begin": "\\b([a-zA-Z0-9_]+)\\(",
+      "beginCaptures": {
+        "1": {
+          "name": "entity.name.variable.pdll"
+        }
+      },
+      "patterns": [
+        {
+          "include": "#expressions"
+        }
+      ],
+      "end": "\\)"
+    },
+    "identifier_expr": {
+      "match": "\\b([a-zA-Z0-9_]+)\\b",
+      "name": "entity.name.variable.pdll"
+    },
+    "op_expr": {
+      "match": "\\b(op)<([0-9a-zA-Z_\\.]*)>",
+      "captures": {
+        "1": {
+          "name": "keyword.other.pdll"
+        },
+        "2": {
+          "name": "variable.other.enummember.pdll"
+        }
+      }
+    },
+    "type_expr": {
+      "patterns": [
+        {
+          "begin": "\\b(type)<",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#string"
+            },
+            {
+              "include": "#string_block"
+            }
+          ],
+          "end": ">"
+        }
+      ]
+    }
+  },
+  "scopeName": "source.pdll"
+}
\ No newline at end of file

diff  --git a/mlir/utils/vscode/pdll-language-configuration.json b/mlir/utils/vscode/pdll-language-configuration.json
new file mode 100644
index 0000000000000..1357db8a9d4db
--- /dev/null
+++ b/mlir/utils/vscode/pdll-language-configuration.json
@@ -0,0 +1,67 @@
+{
+  "comments": {
+    "lineComment": "//"
+  },
+  "brackets": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ]
+  ],
+  "autoClosingPairs": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ],
+    [
+      "\"",
+      "\""
+    ]
+  ],
+  "surroundingPairs": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ],
+    [
+      "\"",
+      "\""
+    ]
+  ]
+}
\ No newline at end of file

diff  --git a/mlir/utils/vscode/src/configWatcher.ts b/mlir/utils/vscode/src/configWatcher.ts
index 47d450086804a..2725015e4cc94 100644
--- a/mlir/utils/vscode/src/configWatcher.ts
+++ b/mlir/utils/vscode/src/configWatcher.ts
@@ -46,7 +46,7 @@ export function activate(mlirContext: MLIRContext) {
   // When a configuration change happens, check to see if we should restart the
   // server.
   mlirContext.subscriptions.push(vscode.workspace.onDidChangeConfiguration(event => {
-    const settings: string[] = [ 'server_path' ];
+    const settings: string[] = [ 'server_path', 'pdll_server_path' ];
     for (const setting of settings) {
       const expandedSetting = `mlir.${setting}`;
       if (event.affectsConfiguration(expandedSetting)) {
@@ -61,21 +61,30 @@ export function activate(mlirContext: MLIRContext) {
 
   // Track the server file in case it changes. We use `fs` here because the
   // server may not be in a workspace directory.
-  const userDefinedServerPath = config.get<string>('server_path');
-  const serverPath =
-      path.resolve((userDefinedServerPath === '') ? 'mlir-lsp-server'
-                                                  : userDefinedServerPath);
-  const fileWatcherConfig = {
-    disableGlobbing : true,
-    followSymlinks : true,
-    ignoreInitial : true,
-  };
-  const fileWatcher = chokidar.watch(serverPath, fileWatcherConfig);
-  fileWatcher.on('all', (_event, _filename, _details) => {
-    promptRestart(
-        'onSettingsChanged',
-        'MLIR language server binary has changed. Do you want to reload the server?');
-  });
-  mlirContext.subscriptions.push(
-      new vscode.Disposable(() => { fileWatcher.close(); }));
+  const settings: string[] = [ 'server_path', 'pdll_server_path' ];
+  for (const setting of settings) {
+    const serverPath = config.get<string>(setting);
+
+    // Check that the path actually exists.
+    if (serverPath === '') {
+      continue;
+    }
+
+    const fileWatcherConfig = {
+      disableGlobbing : true,
+      followSymlinks : true,
+      ignoreInitial : true,
+      awaitWriteFinish : true,
+    };
+    const fileWatcher = chokidar.watch(serverPath, fileWatcherConfig);
+    fileWatcher.on('all', (event, _filename, _details) => {
+      if (event != 'unlink') {
+        promptRestart(
+            'onSettingsChanged',
+            'MLIR language server binary has changed. Do you want to reload the server?');
+      }
+    });
+    mlirContext.subscriptions.push(
+        new vscode.Disposable(() => { fileWatcher.close(); }));
+  }
 }

diff  --git a/mlir/utils/vscode/src/extension.ts b/mlir/utils/vscode/src/extension.ts
index 7c8c9fd6b9692..664146c84fbaf 100644
--- a/mlir/utils/vscode/src/extension.ts
+++ b/mlir/utils/vscode/src/extension.ts
@@ -16,9 +16,13 @@ export function activate(context: vscode.ExtensionContext) {
   // Initialize the commands of the extension.
   context.subscriptions.push(
       vscode.commands.registerCommand('mlir.restart', async () => {
+        // Dispose and reactivate the context. This is essentially the same as
+        // the start of the extension, but we don't re-emit warnings for
+        // uninitialized settings.
         mlirContext.dispose();
-        await mlirContext.activate(outputChannel);
+        await mlirContext.activate(outputChannel,
+                                   /*warnOnEmptyServerPath=*/ false);
       }));
 
-  mlirContext.activate(outputChannel);
+  mlirContext.activate(outputChannel, /*warnOnEmptyServerPath=*/ true);
 }

diff  --git a/mlir/utils/vscode/src/mlirContext.ts b/mlir/utils/vscode/src/mlirContext.ts
index b8a71b97e1656..d6db9a2390113 100644
--- a/mlir/utils/vscode/src/mlirContext.ts
+++ b/mlir/utils/vscode/src/mlirContext.ts
@@ -1,3 +1,4 @@
+import * as fs from 'fs';
 import * as vscode from 'vscode';
 import * as vscodelc from 'vscode-languageclient';
 
@@ -11,16 +12,57 @@ import * as configWatcher from './configWatcher';
 export class MLIRContext implements vscode.Disposable {
   subscriptions: vscode.Disposable[] = [];
   client!: vscodelc.LanguageClient;
+  pdllClient!: vscodelc.LanguageClient;
 
   /**
-   *  Activate the MLIR context, and start the language client.
+   *  Activate the MLIR context, and start the language clients.
    */
-  async activate(outputChannel: vscode.OutputChannel) {
-    // Get the path of the mlir-lsp-server that is used to provide language
+  async activate(outputChannel: vscode.OutputChannel,
+                 warnOnEmptyServerPath: boolean) {
+    // Create the language clients for mlir and pdll.
+    this.pdllClient = this.startLanguageClient(
+        outputChannel, warnOnEmptyServerPath, 'pdll_server_path', 'pdll');
+    this.client = this.startLanguageClient(outputChannel, warnOnEmptyServerPath,
+                                           'server_path', 'mlir');
+
+    // Watch for configuration changes.
+    configWatcher.activate(this);
+  }
+
+  /**
+   *  Start a new language client for the given language.
+   */
+  startLanguageClient(outputChannel: vscode.OutputChannel,
+                      warnOnEmptyServerPath: boolean, serverSettingName: string,
+                      languageName: string): vscodelc.LanguageClient {
+    const clientTitle = languageName.toUpperCase() + ' Language Client';
+
+    // Get the path of the lsp-server that is used to provide language
     // functionality.
-    const userDefinedServerPath = config.get<string>('server_path');
-    const serverPath = (userDefinedServerPath === '') ? 'mlir-lsp-server'
-                                                      : userDefinedServerPath;
+    const serverPath = config.get<string>(serverSettingName);
+
+    // If we aren't emitting warnings on an empty server path, and the server
+    // path is empty, bail.
+    if (!warnOnEmptyServerPath && serverPath === '') {
+      return null;
+    }
+
+    // Check that the file actually exists.
+    if (serverPath === '' || !fs.existsSync(serverPath)) {
+      vscode.window
+          .showErrorMessage(
+              `${clientTitle}: Unable to resolve path for '${
+                  serverSettingName}', please ensure the path is correct`,
+              "Open Setting")
+          .then((value) => {
+            if (value === "Open Setting") {
+              vscode.commands.executeCommand(
+                  'workbench.action.openWorkspaceSettings',
+                  {openToSide : false, query : `mlir.${serverSettingName}`});
+            }
+          });
+      return null;
+    }
 
     // Configure the server options.
     const serverOptions: vscodelc.ServerOptions = {
@@ -38,22 +80,21 @@ export class MLIRContext implements vscode.Disposable {
 
     // Configure the client options.
     const clientOptions: vscodelc.LanguageClientOptions = {
-      documentSelector : [ {scheme : 'file', language : 'mlir'} ],
+      documentSelector : [ {scheme : 'file', language : languageName} ],
       synchronize : {
-        // Notify the server about file changes to *.mlir files contained in the
-        // workspace.
-        fileEvents : vscode.workspace.createFileSystemWatcher('**/*.mlir')
+        // Notify the server about file changes to language files contained in
+        // the workspace.
+        fileEvents :
+            vscode.workspace.createFileSystemWatcher('**/*.' + languageName)
       },
       outputChannel : outputChannel,
     };
 
     // Create the language client and start the client.
-    this.client = new vscodelc.LanguageClient(
-        'mlir-lsp', 'MLIR Language Client', serverOptions, clientOptions);
-    this.subscriptions.push(this.client.start());
-
-    // Watch for configuration changes.
-    configWatcher.activate(this);
+    let languageClient = new vscodelc.LanguageClient(
+        languageName + '-lsp', clientTitle, serverOptions, clientOptions);
+    this.subscriptions.push(languageClient.start());
+    return languageClient;
   }
 
   dispose() {


        


More information about the Mlir-commits mailing list