Skip to content

Commit 0eac473

Browse files
committed
[Basic] Add a utility function for parsing an editor placeholder.
Swift SVN r26214
1 parent 73331c4 commit 0eac473

File tree

5 files changed

+186
-0
lines changed

5 files changed

+186
-0
lines changed
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===--- EditorPlaceholder.h - Handling for editor placeholders -----------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file
14+
/// Provides info about editor placeholders, <#such as this#>.
15+
///
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_BASIC_EDITORPLACEHOLDER_H
19+
#define SWIFT_BASIC_EDITORPLACEHOLDER_H
20+
21+
#include "llvm/ADT/StringRef.h"
22+
#include "swift/Basic/LLVM.h"
23+
24+
namespace swift {
25+
26+
enum class EditorPlaceholderKind {
27+
Basic,
28+
Typed,
29+
};
30+
31+
struct EditorPlaceholderData {
32+
/// Placeholder kind.
33+
EditorPlaceholderKind Kind;
34+
/// The part that is displayed in the editor.
35+
StringRef Display;
36+
/// If kind is \c Typed, this is the type string for the placeholder.
37+
StringRef Type;
38+
/// If kind is \c Typed, this is the type string to be considered for
39+
/// placeholder expansion.
40+
/// It can be same as \c Type or different if \c Type is a typealias.
41+
StringRef TypeForExpansion;
42+
};
43+
44+
/// Deconstructs a placeholder string and returns info about it.
45+
/// \returns None if the \c PlaceholderText is not a valid placeholder string.
46+
Optional<EditorPlaceholderData>
47+
parseEditorPlaceholder(StringRef PlaceholderText);
48+
49+
} // namespace swift
50+
51+
#endif // LLVM_SWIFT_BASIC_EDITORPLACEHOLDER_H
52+

lib/Basic/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_swift_library(swiftBasic
77
DemangleWrappers.cpp
88
DiagnosticConsumer.cpp
99
DiverseStack.cpp
10+
EditorPlaceholder.cpp
1011
JSONSerialization.cpp
1112
LangOptions.cpp
1213
Platform.cpp

lib/Basic/EditorPlaceholder.cpp

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===--- EditorPlaceholder.cpp - Handling for editor placeholders ---------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file
14+
/// Provides info about editor placeholders, <#such as this#>.
15+
///
16+
//===----------------------------------------------------------------------===//
17+
18+
#include "swift/Basic/EditorPlaceholder.h"
19+
#include "llvm/ADT/Optional.h"
20+
21+
using namespace swift;
22+
using namespace llvm;
23+
24+
// Placeholder text must start with '<#' and end with
25+
// '#>'.
26+
//
27+
// Placeholder kinds:
28+
//
29+
// Typed:
30+
// 'T##' display-string '##' type-string ('##' type-for-expansion-string)?
31+
//
32+
// Basic:
33+
// display-string
34+
//
35+
// NOTE: It is required that '##' is not a valid substring of display-string
36+
// or type-string. If this ends up not the case for some reason, we can consider
37+
// adding escaping for '##'.
38+
39+
Optional<EditorPlaceholderData>
40+
swift::parseEditorPlaceholder(StringRef PlaceholderText) {
41+
if (!PlaceholderText.startswith("<#") ||
42+
!PlaceholderText.endswith("#>"))
43+
return None;
44+
45+
PlaceholderText = PlaceholderText.drop_front(2).drop_back(2);
46+
EditorPlaceholderData PHDataBasic;
47+
PHDataBasic.Kind = EditorPlaceholderKind::Basic;
48+
PHDataBasic.Display = PlaceholderText;
49+
50+
if (!PlaceholderText.startswith("T##")) {
51+
// Basic.
52+
return PHDataBasic;
53+
}
54+
55+
// Typed.
56+
EditorPlaceholderData PHDataTyped;
57+
PHDataTyped.Kind = EditorPlaceholderKind::Typed;
58+
59+
assert(PlaceholderText.startswith("T##"));
60+
PlaceholderText = PlaceholderText.drop_front(3);
61+
size_t Pos = PlaceholderText.find("##");
62+
if (Pos == StringRef::npos) {
63+
// Fallback to basic.
64+
return PHDataBasic;
65+
}
66+
PHDataTyped.Display = PlaceholderText.substr(0, Pos);
67+
68+
PlaceholderText = PlaceholderText.substr(Pos+2);
69+
Pos = PlaceholderText.find("##");
70+
if (Pos == StringRef::npos) {
71+
PHDataTyped.Type = PHDataTyped.TypeForExpansion = PlaceholderText;
72+
} else {
73+
PHDataTyped.Type = PlaceholderText.substr(0, Pos);
74+
PHDataTyped.TypeForExpansion = PlaceholderText.substr(Pos+2);
75+
}
76+
77+
return PHDataTyped;
78+
}

unittests/Basic/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_swift_unittest(SwiftBasicTests
99
ADTTests.cpp
1010
ClusteredBitVectorTest.cpp
1111
Demangle.cpp
12+
EditorPlaceholderTest.cpp
1213
SourceManager.cpp
1314
TreeScopedHashTableTests.cpp
1415
StringExtrasTest.cpp
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "swift/Basic/EditorPlaceholder.h"
2+
#include "llvm/ADT/Optional.h"
3+
#include "gtest/gtest.h"
4+
5+
using namespace swift;
6+
7+
TEST(EditorPlaceholder, EditorPlaceholders) {
8+
const char *Text = "<#this is simple#>";
9+
EditorPlaceholderData Data = *parseEditorPlaceholder(Text);
10+
EXPECT_EQ(EditorPlaceholderKind::Basic, Data.Kind);
11+
EXPECT_EQ("this is simple", Data.Display);
12+
EXPECT_TRUE(Data.Type.empty());
13+
EXPECT_TRUE(Data.TypeForExpansion.empty());
14+
15+
Text = "<#T##x: Int##Int#>";
16+
Data = *parseEditorPlaceholder(Text);
17+
EXPECT_EQ(EditorPlaceholderKind::Typed, Data.Kind);
18+
EXPECT_EQ("x: Int", Data.Display);
19+
EXPECT_EQ("Int", Data.Type);
20+
EXPECT_EQ("Int", Data.TypeForExpansion);
21+
22+
Text = "<#T##x: Int##Blah##()->Int#>";
23+
Data = *parseEditorPlaceholder(Text);
24+
EXPECT_EQ(EditorPlaceholderKind::Typed, Data.Kind);
25+
EXPECT_EQ("x: Int", Data.Display);
26+
EXPECT_EQ("Blah", Data.Type);
27+
EXPECT_EQ("()->Int", Data.TypeForExpansion);
28+
29+
// Fallback.
30+
Text = "<#T##x: Int#>";
31+
Data = *parseEditorPlaceholder(Text);
32+
EXPECT_EQ(EditorPlaceholderKind::Basic, Data.Kind);
33+
EXPECT_EQ("T##x: Int", Data.Display);
34+
EXPECT_TRUE(Data.Type.empty());
35+
EXPECT_TRUE(Data.TypeForExpansion.empty());
36+
}
37+
38+
TEST(EditorPlaceholder, InvalidEditorPlaceholders) {
39+
const char *Text = "<#foo";
40+
Optional<EditorPlaceholderData> DataOpt = parseEditorPlaceholder(Text);
41+
EXPECT_FALSE(DataOpt.hasValue());
42+
43+
Text = "foo#>";
44+
DataOpt = parseEditorPlaceholder(Text);
45+
EXPECT_FALSE(DataOpt.hasValue());
46+
47+
Text = "#foo#>";
48+
DataOpt = parseEditorPlaceholder(Text);
49+
EXPECT_FALSE(DataOpt.hasValue());
50+
51+
Text = " <#foo#>";
52+
DataOpt = parseEditorPlaceholder(Text);
53+
EXPECT_FALSE(DataOpt.hasValue());
54+
}

0 commit comments

Comments
 (0)