aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2011-02-13 10:08:08 +1100
committernyamatongwe <unknown>2011-02-13 10:08:08 +1100
commit0e4ae90f839d6ab1bfbd84327ee498a96390172d (patch)
tree93e017190d0f7620d4b7bed9c92fe320a9c67084
parenta66ec5a196b0207fa23c529a13cf5662d11b2b6f (diff)
downloadscintilla-mirror-0e4ae90f839d6ab1bfbd84327ee498a96390172d.tar.gz
Added Merge method to SparseState to make it possible to detect significant
changes in lexers which will require styling beyond the end of the current range.
-rw-r--r--lexers/LexCPP.cxx8
-rw-r--r--lexlib/SparseState.h32
-rw-r--r--test/unit/testSparseState.cxx101
3 files changed, 136 insertions, 5 deletions
diff --git a/lexers/LexCPP.cxx b/lexers/LexCPP.cxx
index 92248f7f0..2e5fdd0d1 100644
--- a/lexers/LexCPP.cxx
+++ b/lexers/LexCPP.cxx
@@ -506,7 +506,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
const int maskActivity = 0x3F;
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
- bool changedRawStringState = rawStringTerminators.Delete(lineCurrent);
+ SparseState<std::string> rawSTNew(lineCurrent);
int activitySet = preproc.IsInactive() ? 0x40 : 0;
@@ -540,8 +540,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
lineCurrent++;
vlls.Add(lineCurrent, preproc);
if (rawStringTerminator != "") {
- rawStringTerminators.Set(lineCurrent-1, rawStringTerminator);
- changedRawStringState = true;
+ rawSTNew.Set(lineCurrent-1, rawStringTerminator);
}
}
@@ -893,7 +892,8 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
}
continuationLine = false;
}
- if (definitionsChanged || changedRawStringState)
+ const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent);
+ if (definitionsChanged || rawStringsChanged)
styler.ChangeLexerState(startPos, startPos + length);
sc.Complete();
}
diff --git a/lexlib/SparseState.h b/lexlib/SparseState.h
index c84fdc861..bd74ecef2 100644
--- a/lexlib/SparseState.h
+++ b/lexlib/SparseState.h
@@ -28,6 +28,7 @@ class SparseState {
return (position == other.position) && (value == other.value);
}
};
+ int positionFirst;
typedef std::vector<State> stateVector;
stateVector states;
@@ -37,6 +38,9 @@ class SparseState {
}
public:
+ SparseState(int positionFirst_=-1) {
+ positionFirst = positionFirst_;
+ }
void Set(int position, T value) {
Delete(position);
if ((states.size() == 0) || (value != states[states.size()-1].value)) {
@@ -69,6 +73,34 @@ public:
size_t size() const {
return states.size();
}
+
+ // Returns true if Merge caused a significant change
+ bool Merge(const SparseState<T> &other, int ignoreAfter) {
+ // Changes caused beyond ignoreAfter are not significant
+ Delete(ignoreAfter+1);
+
+ bool different = true;
+ bool changed = false;
+ typename stateVector::iterator low = Find(other.positionFirst);
+ if (static_cast<size_t>(states.end() - low) == other.states.size()) {
+ // Same number in other as after positionFirst in this
+ different = !std::equal(low, states.end(), other.states.begin());
+ }
+ if (different) {
+ if (low != states.end()) {
+ states.erase(low, states.end());
+ changed = true;
+ }
+ typename stateVector::const_iterator startOther = other.states.begin();
+ if (!states.empty() && states.back().value == startOther->value)
+ startOther++;
+ if (startOther != other.states.end()) {
+ states.insert(states.end(), startOther, other.states.end());
+ changed = true;
+ }
+ }
+ return changed;
+ }
};
#ifdef SCI_NAMESPACE
diff --git a/test/unit/testSparseState.cxx b/test/unit/testSparseState.cxx
index 74f1032b2..a30240d62 100644
--- a/test/unit/testSparseState.cxx
+++ b/test/unit/testSparseState.cxx
@@ -95,13 +95,112 @@ TEST_F(SparseStateTest, ReplaceLast) {
EXPECT_EQ(32, pss->ValueAt(3));
}
-TEST_F(SparseStateTest, CheckOnlyChangeAppended) {
+TEST_F(SparseStateTest, OnlyChangeAppended) {
pss->Set(0, 30);
pss->Set(2, 31);
pss->Set(3, 31);
EXPECT_EQ(2u, pss->size());
}
+TEST_F(SparseStateTest, MergeBetween) {
+ pss->Set(0, 30);
+ pss->Set(2, 32);
+ pss->Set(4, 34);
+ EXPECT_EQ(3u, pss->size());
+
+ SparseState<int> ssAdditions(3);
+ ssAdditions.Set(4, 34);
+ EXPECT_EQ(1u, ssAdditions.size());
+ bool mergeChanged = pss->Merge(ssAdditions,5);
+ EXPECT_EQ(0, mergeChanged);
+
+ ssAdditions.Set(4, 44);
+ EXPECT_EQ(1u, ssAdditions.size());
+ mergeChanged = pss->Merge(ssAdditions,5);
+ EXPECT_EQ(true, mergeChanged);
+ EXPECT_EQ(3u, pss->size());
+ EXPECT_EQ(44, pss->ValueAt(4));
+}
+
+TEST_F(SparseStateTest, MergeAtExisting) {
+ pss->Set(0, 30);
+ pss->Set(2, 32);
+ pss->Set(4, 34);
+ EXPECT_EQ(3u, pss->size());
+
+ SparseState<int> ssAdditions(4);
+ ssAdditions.Set(4, 34);
+ EXPECT_EQ(1u, ssAdditions.size());
+ bool mergeChanged = pss->Merge(ssAdditions,5);
+ EXPECT_EQ(0, mergeChanged);
+
+ ssAdditions.Set(4, 44);
+ EXPECT_EQ(1u, ssAdditions.size());
+ mergeChanged = pss->Merge(ssAdditions,5);
+ EXPECT_EQ(true, mergeChanged);
+ EXPECT_EQ(3u, pss->size());
+ EXPECT_EQ(44, pss->ValueAt(4));
+}
+
+TEST_F(SparseStateTest, MergeWhichRemoves) {
+ pss->Set(0, 30);
+ pss->Set(2, 32);
+ pss->Set(4, 34);
+ EXPECT_EQ(3u, pss->size());
+
+ SparseState<int> ssAdditions(2);
+ ssAdditions.Set(2, 22);
+ EXPECT_EQ(1u, ssAdditions.size());
+ EXPECT_EQ(22, ssAdditions.ValueAt(2));
+ bool mergeChanged = pss->Merge(ssAdditions,5);
+ EXPECT_EQ(true, mergeChanged);
+ EXPECT_EQ(2u, pss->size());
+ EXPECT_EQ(22, pss->ValueAt(2));
+}
+
+TEST_F(SparseStateTest, MergeIgnoreSome) {
+ pss->Set(0, 30);
+ pss->Set(2, 32);
+ pss->Set(4, 34);
+
+ SparseState<int> ssAdditions(2);
+ ssAdditions.Set(2, 32);
+ bool mergeChanged = pss->Merge(ssAdditions,3);
+
+ EXPECT_EQ(0, mergeChanged);
+ EXPECT_EQ(2u, pss->size());
+ EXPECT_EQ(32, pss->ValueAt(2));
+}
+
+TEST_F(SparseStateTest, MergeIgnoreSomeStart) {
+ pss->Set(0, 30);
+ pss->Set(2, 32);
+ pss->Set(4, 34);
+
+ SparseState<int> ssAdditions(2);
+ ssAdditions.Set(2, 32);
+ bool mergeChanged = pss->Merge(ssAdditions,2);
+
+ EXPECT_EQ(0, mergeChanged);
+ EXPECT_EQ(2u, pss->size());
+ EXPECT_EQ(32, pss->ValueAt(2));
+}
+
+TEST_F(SparseStateTest, MergeIgnoreRepeat) {
+ pss->Set(0, 30);
+ pss->Set(2, 32);
+ pss->Set(4, 34);
+
+ SparseState<int> ssAdditions(5);
+ // Appending same value as at end of pss.
+ ssAdditions.Set(5, 34);
+ bool mergeChanged = pss->Merge(ssAdditions,6);
+
+ EXPECT_EQ(0, mergeChanged);
+ EXPECT_EQ(3u, pss->size());
+ EXPECT_EQ(34, pss->ValueAt(4));
+}
+
class SparseStateStringTest : public ::testing::Test {
protected:
virtual void SetUp() {