Skip to content

Commit 084def1

Browse files
committed
Throw exception if group does not exist
1 parent 1731643 commit 084def1

8 files changed

Lines changed: 87 additions & 5 deletions

File tree

PythonScript/project/PythonScript2010.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ xcopy $(ProjectDir)..\python_tests\*.* "e:\notepadtest\unicode\plugins\config\py
264264
<ClCompile Include="..\src\ConsoleDialog.cpp" />
265265
<ClCompile Include="..\src\DynamicIDManager.cpp" />
266266
<ClCompile Include="..\src\EnumsWrapper.cpp" />
267+
<ClCompile Include="..\src\GroupNotFoundException.cpp" />
267268
<ClCompile Include="..\src\HelpController.cpp" />
268269
<ClCompile Include="..\src\Match.cpp" />
269270
<ClCompile Include="..\src\MatchPython.cpp" />
@@ -307,6 +308,7 @@ xcopy $(ProjectDir)..\python_tests\*.* "e:\notepadtest\unicode\plugins\config\py
307308
<ClInclude Include="..\src\ConstString.h" />
308309
<ClInclude Include="..\src\DynamicIDManager.h" />
309310
<ClInclude Include="..\src\Enums.h" />
311+
<ClInclude Include="..\src\GroupNotFoundException.h" />
310312
<ClInclude Include="..\src\HelpController.h" />
311313
<ClInclude Include="..\src\IDAllocator.h" />
312314
<ClInclude Include="..\src\Match.h" />

PythonScript/project/PythonScript2010.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@
144144
<ClCompile Include="..\src\ArgumentException.cpp">
145145
<Filter>Source Files</Filter>
146146
</ClCompile>
147+
<ClCompile Include="..\src\GroupNotFoundException.cpp">
148+
<Filter>Source Files</Filter>
149+
</ClCompile>
147150
</ItemGroup>
148151
<ItemGroup>
149152
<ClInclude Include="..\src\AboutDialog.h">
@@ -308,6 +311,9 @@
308311
<ClInclude Include="..\python_tests\tests\SearchUTF8TestCase.py">
309312
<Filter>PythonTests\Tests</Filter>
310313
</ClInclude>
314+
<ClInclude Include="..\src\GroupNotFoundException.h">
315+
<Filter>Header Files</Filter>
316+
</ClInclude>
311317
</ItemGroup>
312318
<ItemGroup>
313319
<ResourceCompile Include="..\res\PythonScript.rc">

PythonScript/python_tests/tests/ReplaceUTF8PythonFunction.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,13 @@ def test_not_supported_endpos(self):
164164
with self.assertRaisesRegexp(RuntimeError, r"not supported under Notepad\+\+"):
165165
editor.rereplace(r'([a-z]+)', lambda m: m.endpos)
166166

167+
168+
def test_group_index_invalid(self):
169+
with self.assertRaisesRegexp(IndexError, "no such group"):
170+
editor.rereplace(r'([a-z]+)([0-9]+)', lambda m: m.group(3))
171+
172+
def test_group_name_invalid(self):
173+
with self.assertRaisesRegexp(IndexError, "no such group"):
174+
editor.rereplace(r'(?<letters>[a-z]+)(?<numbers>[0-9]+)', lambda m: m.group('somethingelse'))
175+
167176
suite = unittest.TestLoader().loadTestsFromTestCase(ReplaceUTF8PythonFunctionTestCase)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "stdafx.h"
2+
3+
#include "GroupNotFoundException.h"
4+
5+
6+
namespace NppPythonScript
7+
{
8+
9+
10+
void translateGroupNotFoundException(const GroupNotFoundException &e)
11+
{
12+
PyErr_SetString(PyExc_IndexError, e.what());
13+
}
14+
15+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef GROUPNOTFOUNDEXCEPTION_20140214_H
2+
#define GROUPNOTFOUNDEXCEPTION_20140214_H
3+
4+
namespace NppPythonScript
5+
{
6+
7+
class GroupNotFoundException
8+
{
9+
public:
10+
explicit GroupNotFoundException(const char *desc)
11+
: m_desc(desc)
12+
{};
13+
14+
const char *what() const
15+
{ return m_desc.c_str();
16+
}
17+
18+
private:
19+
GroupNotFoundException(); // default constructor disabled
20+
21+
std::string m_desc;
22+
};
23+
24+
25+
void translateGroupNotFoundException(const GroupNotFoundException &e);
26+
27+
}
28+
29+
#endif // GROUPNOTFOUNDEXCEPTION_20140214_H

PythonScript/src/Match.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
#include "stdafx.h"
22
#include "Match.h"
3+
#include "GroupNotFoundException.h"
34

45
namespace NppPythonScript
56
{
67

78

89
boost::python::str Match::py_group_number(int groupNumber)
910
{
11+
GroupDetail *groupDetail = group(groupNumber);
12+
if (NULL == groupDetail)
13+
{
14+
throw GroupNotFoundException("no such group");
15+
}
16+
1017
return boost::python::str(getTextForGroup(group(groupNumber)));
1118
}
1219

1320

1421
boost::python::str Match::py_group_name(boost::python::str pyGroupName)
1522
{
1623
std::string stringGroupName(boost::python::extract<const char *>(pyGroupName.attr("__str__")()));
24+
25+
GroupDetail *groupDetail = groupName(stringGroupName.c_str());
26+
if (NULL == groupDetail)
27+
{
28+
throw GroupNotFoundException("no such group");
29+
}
1730

18-
return boost::python::str(getTextForGroup(groupName(stringGroupName.c_str())));
31+
return boost::python::str(getTextForGroup(groupDetail));
1932
}
2033

2134
boost::python::str Match::getGroup(boost::python::object groupIdentifier)
@@ -105,7 +118,7 @@ boost::python::tuple Match::py_span_name(boost::python::str groupName)
105118

106119
int Match::py_lastindex()
107120
{
108-
int lastGroup = groupCount();
121+
int lastGroup = groupCount() - 1;
109122
while(lastGroup > 0 && !group(lastGroup)->matched())
110123
--lastGroup;
111124

PythonScript/src/Replacer.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ BoostRegexMatch<CharTraitsT>::~BoostRegexMatch()
108108
template <class CharTraitsT>
109109
GroupDetail* BoostRegexMatch<CharTraitsT>::group(int groupNo)
110110
{
111+
if (groupNo < 0 || groupNo >= static_cast<int>(m_match->size()))
112+
{
113+
return NULL;
114+
}
115+
111116
BoostRegexGroupDetail<CharTraitsT>* groupDetail = new BoostRegexGroupDetail<CharTraitsT>((*m_match)[groupNo]);
112117
m_allocatedGroupDetails.push_back(groupDetail);
113118
return groupDetail;
@@ -117,9 +122,8 @@ template <class CharTraitsT>
117122
GroupDetail* BoostRegexMatch<CharTraitsT>::groupName(const char *groupName)
118123
{
119124
CharTraitsT::string_type groupNameU32 = toStringType<CharTraitsT::string_type>(ConstString<char>(groupName));
120-
BoostRegexGroupDetail<CharTraitsT>* groupDetail = new BoostRegexGroupDetail<CharTraitsT>((*m_match)[groupNameU32.c_str()]);
121-
m_allocatedGroupDetails.push_back(groupDetail);
122-
return groupDetail;
125+
int groupIndex = m_match->named_subexpression_index(groupNameU32.c_str(), groupNameU32.c_str() + groupNameU32.size());
126+
return group(groupIndex);
123127
}
124128

125129
template <class CharTraitsT>

PythonScript/src/ScintillaPython.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "MatchPython.h"
99
#include "enums.h"
1010
#include "ArgumentException.h"
11+
#include "GroupNotFoundException.h"
12+
1113

1214
BOOST_PYTHON_MODULE(Npp)
1315
{
@@ -18,6 +20,8 @@ BOOST_PYTHON_MODULE(Npp)
1820
// The class declaration is used as designed, but it messes up Lint.
1921
boost::python::register_exception_translator<out_of_bounds_exception>(&PythonScript::translateOutOfBounds);
2022
boost::python::register_exception_translator<NppPythonScript::ArgumentException>(&NppPythonScript::translateArgumentException);
23+
boost::python::register_exception_translator<NppPythonScript::GroupNotFoundException>(&NppPythonScript::translateGroupNotFoundException);
24+
2125
boost::python::class_<ScintillaWrapper>("Editor", boost::python::no_init)
2226
.def("write", &ScintillaWrapper::AddText, "Add text to the document at current position (alias for addText).")
2327
.def("callback", &ScintillaWrapper::addCallback, "Registers a callback to a Python function when a Scintilla event occurs. e.g. editor.callback(my_function, [ScintillaNotification.CHARADDED])")

0 commit comments

Comments
 (0)