14967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//===--- SortJavaScriptImports.h - Sort ES6 Imports -------------*- C++ -*-===// 24967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// 34967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// The LLVM Compiler Infrastructure 44967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// 54967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 64967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// License. See LICENSE.TXT for details. 74967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// 84967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//===----------------------------------------------------------------------===// 94967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar/// 104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar/// \file 114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar/// \brief This file implements a sort operation for JavaScript ES6 imports. 124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar/// 134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//===----------------------------------------------------------------------===// 144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "SortJavaScriptImports.h" 164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "SortJavaScriptImports.h" 174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "TokenAnalyzer.h" 184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "TokenAnnotator.h" 194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Basic/Diagnostic.h" 204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Basic/DiagnosticOptions.h" 214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Basic/LLVM.h" 224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Basic/SourceLocation.h" 234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Basic/SourceManager.h" 244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Format/Format.h" 254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "llvm/ADT/STLExtras.h" 264967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "llvm/ADT/SmallVector.h" 274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "llvm/Support/Debug.h" 284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include <algorithm> 294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include <string> 304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#define DEBUG_TYPE "format-formatter" 324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarnamespace clang { 344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarnamespace format { 354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarclass FormatTokenLexer; 374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarusing clang::format::FormatStyle; 394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// An imported symbol in a JavaScript ES6 import/export, possibly aliased. 414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarstruct JsImportedSymbol { 424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef Symbol; 434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef Alias; 444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SourceRange Range; 454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool operator==(const JsImportedSymbol &RHS) const { 474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Ignore Range for comparison, it is only used to stitch code together, 484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // but imports at different code locations are still conceptually the same. 494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return Symbol == RHS.Symbol && Alias == RHS.Alias; 504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}; 524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// An ES6 module reference. 544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// 554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// ES6 implements a module system, where individual modules (~= source files) 564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// can reference other modules, either importing symbols from them, or exporting 574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// symbols from them: 584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// import {foo} from 'foo'; 594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// export {foo}; 604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// export {bar} from 'bar'; 614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// 624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// `export`s with URLs are syntactic sugar for an import of the symbol from the 634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// URL, followed by an export of the symbol, allowing this code to treat both 644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// statements more or less identically, with the exception being that `export`s 654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// are sorted last. 664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// 674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// imports and exports support individual symbols, but also a wildcard syntax: 684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// import * as prefix from 'foo'; 694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// export * from 'bar'; 704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// 714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// This struct represents both exports and imports to build up the information 724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// required for sorting module references. 734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarstruct JsModuleReference { 744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool IsExport = false; 754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Module references are sorted into these categories, in order. 764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar enum ReferenceCategory { 774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SIDE_EFFECT, // "import 'something';" 784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ABSOLUTE, // from 'something' 794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar RELATIVE_PARENT, // from '../*' 804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar RELATIVE, // from './*' 814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar }; 824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ReferenceCategory Category = ReferenceCategory::SIDE_EFFECT; 834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // The URL imported, e.g. `import .. from 'url';`. Empty for `export {a, b};`. 844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef URL; 854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Prefix from "import * as prefix". Empty for symbol imports and `export *`. 864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Implies an empty names list. 874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef Prefix; 884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Symbols from `import {SymbolA, SymbolB, ...} from ...;`. 894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SmallVector<JsImportedSymbol, 1> Symbols; 904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Textual position of the import/export, including preceding and trailing 914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // comments. 924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SourceRange Range; 934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}; 944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarbool operator<(const JsModuleReference &LHS, const JsModuleReference &RHS) { 964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (LHS.IsExport != RHS.IsExport) 974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return LHS.IsExport < RHS.IsExport; 984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (LHS.Category != RHS.Category) 994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return LHS.Category < RHS.Category; 1004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT) 1014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Side effect imports might be ordering sensitive. Consider them equal so 1024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // that they maintain their relative order in the stable sort below. 1034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // This retains transitivity because LHS.Category == RHS.Category here. 1044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 1054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Empty URLs sort *last* (for export {...};). 1064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (LHS.URL.empty() != RHS.URL.empty()) 1074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return LHS.URL.empty() < RHS.URL.empty(); 1084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (int Res = LHS.URL.compare_lower(RHS.URL)) 1094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return Res < 0; 1104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // '*' imports (with prefix) sort before {a, b, ...} imports. 1114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (LHS.Prefix.empty() != RHS.Prefix.empty()) 1124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return LHS.Prefix.empty() < RHS.Prefix.empty(); 1134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (LHS.Prefix != RHS.Prefix) 1144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return LHS.Prefix > RHS.Prefix; 1154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 1164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 1174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// JavaScriptImportSorter sorts JavaScript ES6 imports and exports. It is 1194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// implemented as a TokenAnalyzer because ES6 imports have substantial syntactic 1204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// structure, making it messy to sort them using regular expressions. 1214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarclass JavaScriptImportSorter : public TokenAnalyzer { 1224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarpublic: 1234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JavaScriptImportSorter(const Environment &Env, const FormatStyle &Style) 1244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar : TokenAnalyzer(Env, Style), 1254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {} 1264967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar tooling::Replacements 1284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar analyze(TokenAnnotator &Annotator, 1294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FormatTokenLexer &Tokens, tooling::Replacements &Result) override { 1314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(), 1324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar AnnotatedLines.end()); 1334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar const AdditionalKeywords &Keywords = Tokens.getKeywords(); 1354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SmallVector<JsModuleReference, 16> References; 1364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar AnnotatedLine *FirstNonImportLine; 1374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar std::tie(References, FirstNonImportLine) = 1384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar parseModuleReferences(Keywords, AnnotatedLines); 1394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (References.empty()) 1414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return Result; 1424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SmallVector<unsigned, 16> Indices; 1444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for (unsigned i = 0, e = References.size(); i != e; ++i) 1454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Indices.push_back(i); 1464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar std::stable_sort(Indices.begin(), Indices.end(), 1474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar [&](unsigned LHSI, unsigned RHSI) { 1484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return References[LHSI] < References[RHSI]; 1494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar }); 1504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool ReferencesInOrder = std::is_sorted(Indices.begin(), Indices.end()); 1514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar std::string ReferencesText; 1534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool SymbolsInOrder = true; 1544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for (unsigned i = 0, e = Indices.size(); i != e; ++i) { 1554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsModuleReference Reference = References[Indices[i]]; 1564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (appendReference(ReferencesText, Reference)) 1574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SymbolsInOrder = false; 1584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (i + 1 < e) { 1594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Insert breaks between imports and exports. 1604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ReferencesText += "\n"; 1614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Separate imports groups with two line breaks, but keep all exports 1624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // in a single group. 1634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!Reference.IsExport && 1644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar (Reference.IsExport != References[Indices[i + 1]].IsExport || 1654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Category != References[Indices[i + 1]].Category)) 1664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ReferencesText += "\n"; 1674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (ReferencesInOrder && SymbolsInOrder) 1714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return Result; 1724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SourceRange InsertionPoint = References[0].Range; 1744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd()); 1754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // The loop above might collapse previously existing line breaks between 1774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // import blocks, and thus shrink the file. SortIncludes must not shrink 1784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // overall source length as there is currently no re-calculation of ranges 1794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // after applying source sorting. 1804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // This loop just backfills trailing spaces after the imports, which are 1814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // harmless and will be stripped by the subsequent formatting pass. 1824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // FIXME: A better long term fix is to re-calculate Ranges after sorting. 1834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar unsigned PreviousSize = getSourceText(InsertionPoint).size(); 1844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar while (ReferencesText.size() < PreviousSize) { 1854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ReferencesText += " "; 1864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Separate references from the main code body of the file. 1894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (FirstNonImportLine && FirstNonImportLine->First->NewlinesBefore < 2) 1904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ReferencesText += "\n"; 1914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar DEBUG(llvm::dbgs() << "Replacing imports:\n" 1934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << getSourceText(InsertionPoint) << "\nwith:\n" 1944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << ReferencesText << "\n"); 1954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Result.insert(tooling::Replacement( 1964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Env.getSourceManager(), CharSourceRange::getCharRange(InsertionPoint), 1974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ReferencesText)); 1984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return Result; 2004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarprivate: 2034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FormatToken *Current; 2044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FormatToken *LineEnd; 2054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FormatToken invalidToken; 2074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef FileContents; 2094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar void skipComments() { Current = skipComments(Current); } 2114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FormatToken *skipComments(FormatToken *Tok) { 2134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar while (Tok && Tok->is(tok::comment)) 2144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Tok = Tok->Next; 2154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return Tok; 2164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar void nextToken() { 2194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Current = Current->Next; 2204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar skipComments(); 2214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!Current || Current == LineEnd->Next) { 2224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Set the current token to an invalid token, so that further parsing on 2234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // this line fails. 2244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar invalidToken.Tok.setKind(tok::unknown); 2254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Current = &invalidToken; 2264967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef getSourceText(SourceRange Range) { 2304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return getSourceText(Range.getBegin(), Range.getEnd()); 2314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef getSourceText(SourceLocation Begin, SourceLocation End) { 2344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar const SourceManager &SM = Env.getSourceManager(); 2354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return FileContents.substr(SM.getFileOffset(Begin), 2364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SM.getFileOffset(End) - SM.getFileOffset(Begin)); 2374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Appends ``Reference`` to ``Buffer``, returning true if text within the 2404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // ``Reference`` changed (e.g. symbol order). 2414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool appendReference(std::string &Buffer, JsModuleReference &Reference) { 2424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Sort the individual symbols within the import. 2434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // E.g. `import {b, a} from 'x';` -> `import {a, b} from 'x';` 2444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SmallVector<JsImportedSymbol, 1> Symbols = Reference.Symbols; 2454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar std::stable_sort( 2464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Symbols.begin(), Symbols.end(), 2474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar [&](const JsImportedSymbol &LHS, const JsImportedSymbol &RHS) { 2484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return LHS.Symbol.compare_lower(RHS.Symbol) < 0; 2494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar }); 2504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Symbols == Reference.Symbols) { 2514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // No change in symbol order. 2524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef ReferenceStmt = getSourceText(Reference.Range); 2534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Buffer += ReferenceStmt; 2544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 2554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Stitch together the module reference start... 2574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SourceLocation SymbolsStart = Reference.Symbols.front().Range.getBegin(); 2584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SourceLocation SymbolsEnd = Reference.Symbols.back().Range.getEnd(); 2594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Buffer += getSourceText(Reference.Range.getBegin(), SymbolsStart); 2604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // ... then the references in order ... 2614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for (auto I = Symbols.begin(), E = Symbols.end(); I != E; ++I) { 2624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (I != Symbols.begin()) 2634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Buffer += ","; 2644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Buffer += getSourceText(I->Range); 2654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // ... followed by the module reference end. 2674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Buffer += getSourceText(SymbolsEnd, Reference.Range.getEnd()); 2684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return true; 2694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 2714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Parses module references in the given lines. Returns the module references, 2724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // and a pointer to the first "main code" line if that is adjacent to the 2734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // affected lines of module references, nullptr otherwise. 2744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar std::pair<SmallVector<JsModuleReference, 16>, AnnotatedLine*> 2754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar parseModuleReferences(const AdditionalKeywords &Keywords, 2764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SmallVector<JsModuleReference, 16> References; 2784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SourceLocation Start; 2794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool FoundLines = false; 2804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar AnnotatedLine *FirstNonImportLine = nullptr; 2814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for (auto Line : AnnotatedLines) { 2824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!Line->Affected) { 2834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Only sort the first contiguous block of affected lines. 2844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (FoundLines) 2854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar break; 2864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else 2874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar continue; 2884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 2894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Current = Line->First; 2904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar LineEnd = Line->Last; 2914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar skipComments(); 2924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Start.isInvalid() || References.empty()) 2934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // After the first file level comment, consider line comments to be part 2944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // of the import that immediately follows them by using the previously 2954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // set Start. 2964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Start = Line->First->Tok.getLocation(); 2974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!Current) 2984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar continue; // Only comments on this line. 2994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FoundLines = true; 3004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsModuleReference Reference; 3014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Range.setBegin(Start); 3024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!parseModuleReference(Keywords, Reference)) { 3034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar FirstNonImportLine = Line; 3044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar break; 3054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Range.setEnd(LineEnd->Tok.getEndLoc()); 3074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar DEBUG({ 3084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar llvm::dbgs() << "JsModuleReference: {" 3094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << "is_export: " << Reference.IsExport 3104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << ", cat: " << Reference.Category 3114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << ", url: " << Reference.URL 3124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << ", prefix: " << Reference.Prefix; 3134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for (size_t i = 0; i < Reference.Symbols.size(); ++i) 3144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar llvm::dbgs() << ", " << Reference.Symbols[i].Symbol << " as " 3154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << Reference.Symbols[i].Alias; 3164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar llvm::dbgs() << ", text: " << getSourceText(Reference.Range); 3174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar llvm::dbgs() << "}\n"; 3184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar }); 3194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar References.push_back(Reference); 3204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Start = SourceLocation(); 3214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return std::make_pair(References, FirstNonImportLine); 3234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Parses a JavaScript/ECMAScript 6 module reference. 3264967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // See http://www.ecma-international.org/ecma-262/6.0/#sec-scripts-and-modules 3274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // for grammar EBNF (production ModuleItem). 3284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool parseModuleReference(const AdditionalKeywords &Keywords, 3294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsModuleReference &Reference) { 3304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!Current || !Current->isOneOf(Keywords.kw_import, tok::kw_export)) 3314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 3324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.IsExport = Current->is(tok::kw_export); 3334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 3354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isStringLiteral() && !Reference.IsExport) { 3364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // "import 'side-effect';" 3374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Category = JsModuleReference::ReferenceCategory::SIDE_EFFECT; 3384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.URL = 3394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Current->TokenText.substr(1, Current->TokenText.size() - 2); 3404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return true; 3414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!parseModuleBindings(Keywords, Reference)) 3444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 3454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 3464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->is(Keywords.kw_from)) { 3484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // imports have a 'from' clause, exports might not. 3494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 3504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!Current->isStringLiteral()) 3514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 3524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // URL = TokenText without the quotes. 3534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.URL = 3544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Current->TokenText.substr(1, Current->TokenText.size() - 2); 3554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Reference.URL.startswith("..")) 3564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Category = 3574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsModuleReference::ReferenceCategory::RELATIVE_PARENT; 3584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else if (Reference.URL.startswith(".")) 3594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE; 3604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else 3614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Category = JsModuleReference::ReferenceCategory::ABSOLUTE; 3624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } else { 3634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // w/o URL groups with "empty". 3644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE; 3654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return true; 3674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool parseModuleBindings(const AdditionalKeywords &Keywords, 3704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsModuleReference &Reference) { 3714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (parseStarBinding(Keywords, Reference)) 3724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return true; 3734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return parseNamedBindings(Keywords, Reference); 3744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool parseStarBinding(const AdditionalKeywords &Keywords, 3774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsModuleReference &Reference) { 3784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // * as prefix from '...'; 3794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isNot(tok::star)) 3804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 3814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 3824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isNot(Keywords.kw_as)) 3834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 3844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 3854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isNot(tok::identifier)) 3864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 3874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Prefix = Current->TokenText; 3884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return true; 3894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 3904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool parseNamedBindings(const AdditionalKeywords &Keywords, 3924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsModuleReference &Reference) { 3934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isNot(tok::l_brace)) 3944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 3954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // {sym as alias, sym2 as ...} from '...'; 3974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 3984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar while (true) { 3994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->is(tok::r_brace)) 4004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return true; 4014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isNot(tok::identifier)) 4024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 4034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JsImportedSymbol Symbol; 4054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Symbol.Symbol = Current->TokenText; 4064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Make sure to include any preceding comments. 4074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Symbol.Range.setBegin( 4084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Current->getPreviousNonComment()->Next->WhitespaceRange.getBegin()); 4094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 4104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->is(Keywords.kw_as)) { 4124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 4134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isNot(tok::identifier)) 4144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 4154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Symbol.Alias = Current->TokenText; 4164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 4174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 4184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Symbol.Range.setEnd(Current->Tok.getLocation()); 4194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Reference.Symbols.push_back(Symbol); 4204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->is(tok::r_brace)) 4224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return true; 4234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (Current->isNot(tok::comma)) 4244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return false; 4254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar nextToken(); 4264967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 4274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 4284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}; 4294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainartooling::Replacements sortJavaScriptImports(const FormatStyle &Style, 4314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef Code, 4324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ArrayRef<tooling::Range> Ranges, 4334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar StringRef FileName) { 4344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // FIXME: Cursor support. 4354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar std::unique_ptr<Environment> Env = 4364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Environment::CreateVirtualEnvironment(Code, FileName, Ranges); 4374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar JavaScriptImportSorter Sorter(*Env, Style); 4384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return Sorter.process(); 4394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 4404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end namespace format 4424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end namespace clang 443