break;
}
}
- if (Contexts.back().ColonIsDictLiteral ||
- Style.Language == FormatStyle::LK_Proto ||
- Style.Language == FormatStyle::LK_TextProto) {
+ if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) ||
+ Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||
+ Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {
+ Tok->setType(TT_ModulePartitionColon);
+ } else if (Contexts.back().ColonIsDictLiteral ||
+ Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) {
Tok->setType(TT_DictLiteral);
if (Style.Language == FormatStyle::LK_TextProto) {
if (FormatToken *Previous = Tok->getPreviousNonComment())
auto HasExistingWhitespace = [&Right]() {
return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
};
+
if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
return true; // Never ever merge two identifiers.
return true;
if (Style.isCpp()) {
+ // Space between import <iostream>.
+ // or import .....;
+ if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))
+ return true;
+ // No space between module :.
+ if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&
+ Right.is(TT_ModulePartitionColon))
+ return true;
+ // No space between import foo:bar but keep a space between import :bar;
+ if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))
+ return false;
+ // No space between :bar;
+ if (Left.is(TT_ModulePartitionColon) &&
+ Right.isOneOf(tok::identifier, tok::kw_private))
+ return false;
+ if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&
+ Line.First->is(Keywords.kw_import))
+ return false;
+
if (Left.is(tok::kw_operator))
return Right.is(tok::coloncolon);
if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&
return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);
}
+void UnwrappedLineParser::parseModuleImport() {
+ nextToken();
+ while (!eof()) {
+ if (FormatTok->is(tok::colon)) {
+ FormatTok->setType(TT_ModulePartitionColon);
+ }
+ // Handle import <foo/bar.h> as we would an include statement.
+ else if (FormatTok->is(tok::less)) {
+ nextToken();
+ while (!FormatTok->isOneOf(tok::semi, tok::greater, tok::eof)) {
+ // Mark tokens up to the trailing line comments as implicit string
+ // literals.
+ if (FormatTok->isNot(tok::comment) &&
+ !FormatTok->TokenText.startswith("//"))
+ FormatTok->setType(TT_ImplicitStringLiteral);
+ nextToken();
+ }
+ }
+ if (FormatTok->is(tok::semi)) {
+ nextToken();
+ break;
+ }
+ nextToken();
+ }
+
+ addUnwrappedLine();
+ return;
+}
+
// readTokenWithJavaScriptASI reads the next token and terminates the current
// line if JavaScript Automatic Semicolon Insertion must
// happen between the current token and the next token.
addUnwrappedLine();
return;
}
+ if (Style.isCpp()) {
+ parseModuleImport();
+ return;
+ }
}
if (Style.isCpp() &&
FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
verifyFormat("auto(*p)() = f;"); // actually a declaration; TODO FIXME
}
+TEST_F(FormatTest, Cpp20ModulesSupport) {
+ FormatStyle Style = getLLVMStyle();
+ Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
+ Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+
+ verifyFormat("export import foo;", Style);
+ verifyFormat("export import foo:bar;", Style);
+ verifyFormat("export import foo.bar;", Style);
+ verifyFormat("export import foo.bar:baz;", Style);
+ verifyFormat("export import :bar;", Style);
+ verifyFormat("export module foo:bar;", Style);
+ verifyFormat("export module foo;", Style);
+ verifyFormat("export module foo.bar;", Style);
+ verifyFormat("export module foo.bar:baz;", Style);
+ verifyFormat("export import <string_view>;", Style);
+
+ verifyFormat("export type_name var;", Style);
+ verifyFormat("template <class T> export using A = B<T>;", Style);
+ verifyFormat("export using A = B;", Style);
+ verifyFormat("export int func() {\n"
+ " foo();\n"
+ "}",
+ Style);
+ verifyFormat("export struct {\n"
+ " int foo;\n"
+ "};",
+ Style);
+ verifyFormat("export {\n"
+ " int foo;\n"
+ "};",
+ Style);
+ verifyFormat("export export char const *hello() { return \"hello\"; }");
+
+ verifyFormat("import bar;", Style);
+ verifyFormat("import foo.bar;", Style);
+ verifyFormat("import foo:bar;", Style);
+ verifyFormat("import :bar;", Style);
+ verifyFormat("import <ctime>;", Style);
+ verifyFormat("import \"header\";", Style);
+
+ verifyFormat("module foo;", Style);
+ verifyFormat("module foo:bar;", Style);
+ verifyFormat("module foo.bar;", Style);
+ verifyFormat("module;", Style);
+
+ verifyFormat("export namespace hi {\n"
+ "const char *sayhi();\n"
+ "}",
+ Style);
+
+ verifyFormat("module :private;", Style);
+ verifyFormat("import <foo/bar.h>;", Style);
+ verifyFormat("import foo...bar;", Style);
+ verifyFormat("import ..........;", Style);
+ verifyFormat("module foo:private;", Style);
+ verifyFormat("import a", Style);
+ verifyFormat("module a", Style);
+ verifyFormat("export import a", Style);
+ verifyFormat("export module a", Style);
+
+ verifyFormat("import", Style);
+ verifyFormat("module", Style);
+ verifyFormat("export", Style);
+}
+
} // namespace
} // namespace format
} // namespace clang