forked from facebook/hermes
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: Add the DependencyExtractor class, which takes an AST and extracts the dependencies using RecursiveVisitor. It currently does nothing. Create a CLI for it to be able to test it. Reviewed By: tmikov Differential Revision: D21091835 fbshipit-source-id: a7ac6caa021ef610000acd486976ad6252b852b7
- Loading branch information
1 parent
1f798b0
commit 319414b
Showing
9 changed files
with
233 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#ifndef HERMES_AST_DEPENDENCYEXTRACTOR_H | ||
#define HERMES_AST_DEPENDENCYEXTRACTOR_H | ||
|
||
#include "hermes/AST/Context.h" | ||
#include "hermes/AST/ESTree.h" | ||
|
||
namespace hermes { | ||
|
||
/// The kind of dependency, used to distinguish between the different ways to | ||
/// pull an external module into the file. | ||
enum class DependencyKind { | ||
// import {x} from 'source'; | ||
ESM, | ||
// import type {x} from 'source'; | ||
Type, | ||
// require('source'); | ||
Require, | ||
// import('source'); | ||
Async, | ||
// JSResource('source'); | ||
Resource, | ||
// PrefetchedJSResource('source'); | ||
PrefetchedResource, | ||
// graphql`fragment source` and others; | ||
GraphQL, | ||
}; | ||
|
||
inline const char *dependencyKindStr(DependencyKind kind) { | ||
switch (kind) { | ||
case DependencyKind::ESM: | ||
return "ESM"; | ||
case DependencyKind::Type: | ||
return "Type"; | ||
case DependencyKind::Require: | ||
return "Require"; | ||
case DependencyKind::Async: | ||
return "Async"; | ||
case DependencyKind::Resource: | ||
return "Resource"; | ||
case DependencyKind::PrefetchedResource: | ||
return "PrefetchedResource"; | ||
case DependencyKind::GraphQL: | ||
return "GraphQL"; | ||
} | ||
} | ||
|
||
/// Represents a single dependency from a source file. | ||
struct Dependency { | ||
/// The target file name of the dependency. | ||
/// For example, `require('name')` is used to indicate a Require dependency on | ||
/// 'name'. | ||
std::string name; | ||
|
||
/// The kind of the dependency. | ||
DependencyKind kind; | ||
}; | ||
|
||
/// Extract any dependencies in \p node and its children. | ||
/// \return a list of Dependency indicating what the target is, as well as the | ||
/// kind of dependency. | ||
std::vector<Dependency> extractDependencies( | ||
Context &astContext, | ||
ESTree::Node *node); | ||
|
||
} // namespace hermes | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Copyright (c) Facebook, Inc. and its affiliates. | ||
# | ||
# This source code is licensed under the MIT license found in the | ||
# LICENSE file in the root directory of this source tree. | ||
|
||
set(source_files | ||
DependencyExtractor.cpp | ||
) | ||
|
||
add_hermes_library(hermesDependencyExtractor STATIC ${source_files} | ||
LINK_LIBS | ||
hermesAST | ||
hermesParser | ||
hermesSupport | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#include "hermes/DependencyExtractor/DependencyExtractor.h" | ||
|
||
#include "hermes/AST/RecursiveVisitor.h" | ||
|
||
namespace hermes { | ||
|
||
using namespace hermes::ESTree; | ||
|
||
/// Visitor for extracting dependencies from a given node. | ||
/// Reports errors on encountering nodes which should introduce dependencies | ||
/// but are malformed. | ||
class DependencyExtractor { | ||
/// Storage for the extracted dependencies. | ||
std::vector<Dependency> deps_{}; | ||
|
||
/// SourceErrorManager for reporting errors, e.g. for invalid require() calls. | ||
SourceErrorManager &sm_; | ||
|
||
public: | ||
DependencyExtractor(Context &astContext) | ||
: sm_(astContext.getSourceErrorManager()) {} | ||
|
||
std::vector<Dependency> &getDeps() { | ||
return deps_; | ||
} | ||
|
||
/// Perform the extraction on whole AST. | ||
void doIt(Node *rootNode) { | ||
visitESTreeNode(*this, rootNode); | ||
} | ||
|
||
/// Stub which catches all nodes we don't need to directly extract | ||
/// dependencies from. | ||
void visit(Node *node) { | ||
visitESTreeChildren(*this, node); | ||
} | ||
}; | ||
|
||
std::vector<Dependency> extractDependencies(Context &astContext, Node *node) { | ||
DependencyExtractor extract{astContext}; | ||
extract.doIt(node); | ||
return std::move(extract.getDeps()); | ||
} | ||
|
||
} // namespace hermes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Copyright (c) Facebook, Inc. and its affiliates. | ||
# | ||
# This source code is licensed under the MIT license found in the | ||
# LICENSE file in the root directory of this source tree. | ||
|
||
set(HERMES_LINK_COMPONENTS LLVHSupport) | ||
|
||
add_hermes_tool(dependency-extractor | ||
dependency-extractor.cpp | ||
${ALL_HEADER_FILES} | ||
) | ||
|
||
target_link_libraries(dependency-extractor | ||
hermesAST | ||
hermesDependencyExtractor | ||
hermesParser | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#include "hermes/DependencyExtractor/DependencyExtractor.h" | ||
#include "hermes/Parser/JSParser.h" | ||
|
||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/Support/CommandLine.h" | ||
#include "llvm/Support/FileSystem.h" | ||
#include "llvm/Support/InitLLVM.h" | ||
#include "llvm/Support/MemoryBuffer.h" | ||
#include "llvm/Support/PrettyStackTrace.h" | ||
#include "llvm/Support/Signals.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
|
||
static llvm::cl::opt<std::string> InputFilename( | ||
llvm::cl::desc("input file"), | ||
llvm::cl::Positional); | ||
|
||
using namespace hermes; | ||
|
||
int main(int argc, char **argv) { | ||
// Normalize the arg vector. | ||
llvm::InitLLVM initLLVM(argc, argv); | ||
llvm::sys::PrintStackTraceOnErrorSignal("dependency-extractor"); | ||
llvm::PrettyStackTraceProgram X(argc, argv); | ||
llvm::llvm_shutdown_obj Y; | ||
llvm::cl::ParseCommandLineOptions( | ||
argc, argv, "Hermes JS dependency extractor\n"); | ||
|
||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr = | ||
llvm::MemoryBuffer::getFile(InputFilename); | ||
|
||
if (!fileBufOrErr) { | ||
llvm::errs() << "Error: fail to open file: " << InputFilename << ": " | ||
<< fileBufOrErr.getError().message() << "\n"; | ||
return -1; | ||
} | ||
|
||
auto fileBuf = std::move(fileBufOrErr.get()); | ||
|
||
auto context = std::make_shared<Context>(); | ||
#if HERMES_PARSE_JSX | ||
context->setParseJSX(true); | ||
#endif | ||
#if HERMES_PARSE_FLOW | ||
context->setParseFlow(true); | ||
#endif | ||
|
||
int fileBufId = | ||
context->getSourceErrorManager().addNewSourceBuffer(std::move(fileBuf)); | ||
auto mode = parser::FullParse; | ||
|
||
parser::JSParser jsParser(*context, fileBufId, mode); | ||
llvm::Optional<ESTree::ProgramNode *> parsedJs = jsParser.parse(); | ||
|
||
if (!parsedJs) | ||
return -1; | ||
|
||
auto deps = extractDependencies(*context, *parsedJs); | ||
for (const auto &dep : deps) { | ||
llvm::outs() << dependencyKindStr(dep.kind) << " | " << dep.name << '\n'; | ||
} | ||
|
||
return 0; | ||
} |