summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.76.0/src/chunk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.76.0/src/chunk.cpp')
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.76.0/src/chunk.cpp896
1 files changed, 896 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.76.0/src/chunk.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.76.0/src/chunk.cpp
new file mode 100644
index 00000000..125879b6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.76.0/src/chunk.cpp
@@ -0,0 +1,896 @@
+/**
+ * @file chunk.cpp
+ * Manages and navigates the list of chunks.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "chunk.h"
+
+#include "ListManager.h"
+#include "prototypes.h"
+#include "space.h"
+
+static ChunkListManager gChunkList; // global chunk list
+
+
+/*
+ * Chunk class methods
+ */
+
+// Null Chunk
+Chunk Chunk::NullChunk(true);
+Chunk *const Chunk::NullChunkPtr(&Chunk::NullChunk);
+
+
+void Chunk::CopyFrom(const Chunk &o)
+{
+ m_type = o.m_type;
+ m_parentType = o.m_parentType;
+ m_origLine = o.m_origLine;
+ m_origCol = o.m_origCol;
+ m_origColEnd = o.m_origColEnd;
+ m_origPrevSp = o.m_origPrevSp;
+ m_column = o.m_column;
+ m_columnIndent = o.m_columnIndent;
+ m_nlCount = o.m_nlCount;
+ m_nlColumn = o.m_nlColumn;
+ m_level = o.m_level;
+ m_braceLevel = o.m_braceLevel;
+ m_ppLevel = o.m_ppLevel;
+ m_afterTab = o.m_afterTab;
+
+ m_flags = o.m_flags;
+ m_alignmentData = o.m_alignmentData;
+ m_indentData = o.m_indentData;
+
+ m_next = Chunk::NullChunkPtr;
+ m_prev = Chunk::NullChunkPtr;
+ m_parent = Chunk::NullChunkPtr;
+
+ m_str = o.m_str;
+ m_trackingData = o.m_trackingData;
+}
+
+
+void Chunk::Reset()
+{
+ m_type = CT_NONE;
+ m_parentType = CT_NONE;
+ m_origLine = 0;
+ m_origCol = 0;
+ m_origColEnd = 0;
+ m_origPrevSp = 0;
+ m_column = 0;
+ m_columnIndent = 0;
+ m_nlCount = 0;
+ m_nlColumn = 0;
+ m_level = 0;
+ m_braceLevel = 0;
+ m_ppLevel = 999; // use a big value to find some errors
+ m_afterTab = false;
+
+ m_flags = PCF_NONE;
+ memset(&m_alignmentData, 0, sizeof(m_alignmentData));
+ memset(&m_indentData, 0, sizeof(m_indentData));
+
+ m_next = Chunk::NullChunkPtr;
+ m_prev = Chunk::NullChunkPtr;
+ m_parent = Chunk::NullChunkPtr;
+
+ // for debugging purpose only
+ m_str.clear();
+ m_trackingData = nullptr;
+}
+
+
+const char *Chunk::ElidedText(char *for_the_copy) const
+{
+ const char *test_it = Text();
+ size_t test_it_length = strlen(test_it);
+
+ size_t truncate_value = uncrustify::options::debug_truncate();
+
+ if (truncate_value != 0)
+ {
+ if (test_it_length > truncate_value)
+ {
+ memset(for_the_copy, 0, 1000);
+
+ if (test_it_length < truncate_value + 30)
+ {
+ strncpy(for_the_copy, test_it, truncate_value - 30);
+ for_the_copy[truncate_value - 30] = 0;
+ }
+ else
+ {
+ strncpy(for_the_copy, test_it, truncate_value);
+ for_the_copy[truncate_value] = 0;
+ }
+ char *message = strcat(for_the_copy, " ... <The string is truncated>");
+
+ return(message);
+ }
+ else
+ {
+ return(test_it);
+ }
+ }
+ return(test_it);
+}
+
+
+Chunk *Chunk::GetNext(const E_Scope scope) const
+{
+ if (scope == E_Scope::ALL)
+ {
+ return(m_next);
+ }
+ Chunk *pc = m_next;
+
+ if (TestFlags(PCF_IN_PREPROC))
+ {
+ // If in a preproc, return a null chunk if trying to leave
+ if (!pc->TestFlags(PCF_IN_PREPROC))
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+ }
+
+ // Not in a preproc, skip any preproc
+ while ( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_IN_PREPROC))
+ {
+ pc = pc->m_next;
+ }
+ return(pc);
+} // Chunk::GetNext
+
+
+Chunk *Chunk::GetPrev(const E_Scope scope) const
+{
+ if (scope == E_Scope::ALL)
+ {
+ return(m_prev);
+ }
+ Chunk *pc = m_prev;
+
+ if (TestFlags(PCF_IN_PREPROC))
+ {
+ // If in a preproc, return a null chunk if trying to leave
+ if (!pc->TestFlags(PCF_IN_PREPROC))
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+ }
+
+ // Not in a preproc, skip any preproc
+ while ( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_IN_PREPROC))
+ {
+ pc = pc->m_prev;
+ }
+ return(pc);
+} // Chunk::GetPrev
+
+
+static void chunk_log(Chunk *pc, const char *text);
+
+
+Chunk *Chunk::GetHead()
+{
+ return(gChunkList.GetHead());
+}
+
+
+Chunk *Chunk::GetTail()
+{
+ return(gChunkList.GetTail());
+}
+
+
+Chunk::T_SearchFnPtr Chunk::GetSearchFn(const E_Direction dir)
+{
+ return((dir == E_Direction::FORWARD) ? &Chunk::GetNext : &Chunk::GetPrev);
+}
+
+
+Chunk *Chunk::Search(const T_CheckFnPtr checkFn, const E_Scope scope,
+ const E_Direction dir, const bool cond) const
+{
+ T_SearchFnPtr searchFnPtr = GetSearchFn(dir);
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ do // loop over the chunk list
+ {
+ pc = (pc->*searchFnPtr)(scope); // in either direction while
+ } while ( pc->IsNotNullChunk() // the end of the list was not reached yet
+ && ((pc->*checkFn)() != cond)); // and the demanded chunk was not found either
+
+ return(pc); // the latest chunk is the searched one
+}
+
+
+bool Chunk::IsOnSameLine(const Chunk *end) const
+{
+ if (IsNullChunk())
+ {
+ return(false);
+ }
+ Chunk *tmp = GetNext();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp != end)
+ {
+ if (tmp->Is(CT_NEWLINE))
+ {
+ return(false);
+ }
+ tmp = tmp->GetNext();
+ }
+ return(true);
+}
+
+
+Chunk *Chunk::SearchTypeLevel(const E_Token type, const E_Scope scope,
+ const E_Direction dir, const int level) const
+{
+ T_SearchFnPtr searchFnPtr = GetSearchFn(dir);
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ do // loop over the chunk list
+ {
+ pc = (pc->*searchFnPtr)(scope); // in either direction while
+ } while ( pc->IsNotNullChunk() // the end of the list was not reached yet
+ && (!pc->IsTypeAndLevel(type, level))); // and the chunk was not found either
+
+ return(pc); // the latest chunk is the searched one
+}
+
+
+Chunk *Chunk::SearchStringLevel(const char *cStr, const size_t len, int level,
+ const E_Scope scope, const E_Direction dir) const
+{
+ T_SearchFnPtr searchFnPtr = GetSearchFn(dir);
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ do // loop over the chunk list
+ {
+ pc = (pc->*searchFnPtr)(scope); // in either direction while
+ } while ( pc->IsNotNullChunk() // the end of the list was not reached yet
+ && !pc->IsStringAndLevel(cStr, len, true, level)); // and the demanded chunk was not found either
+
+ return(pc); // the latest chunk is the searched one
+}
+
+
+Chunk *Chunk::SearchPpa(const T_CheckFnPtr checkFn, const bool cond) const
+{
+ if (!TestFlags(PCF_IN_PREPROC))
+ {
+ // if not in preprocessor, do a regular search
+ return(Search(checkFn, E_Scope::ALL, E_Direction::FORWARD, cond));
+ }
+ Chunk *pc = GetNext();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (!pc->TestFlags(PCF_IN_PREPROC))
+ {
+ // Bail if we run off the end of the preprocessor directive, but return
+ // the token because the caller may need to know where the search ended
+ assert(pc->Is(CT_NEWLINE));
+ return(pc);
+ }
+
+ if (pc->Is(CT_NL_CONT))
+ {
+ // Skip line continuation
+ pc = pc->GetNext();
+ continue;
+ }
+
+ if ((pc->*checkFn)() == cond)
+ {
+ // Requested token was found
+ return(pc);
+ }
+ pc = pc->GetNext();
+ }
+ // Ran out of tokens
+ return(Chunk::NullChunkPtr);
+}
+
+
+static void chunk_log_msg(Chunk *chunk, const log_sev_t log, const char *str)
+{
+ LOG_FMT(log, "%s orig line is %zu, orig col is %zu, ",
+ str, chunk->GetOrigLine(), chunk->GetOrigCol());
+
+ if (chunk->Is(CT_NEWLINE))
+ {
+ LOG_FMT(log, "<Newline>,\n");
+ }
+ else if (chunk->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(log, "<VBRACE_OPEN>,\n");
+ }
+ else if (chunk->Is(CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(log, "<VBRACE_CLOSE>,\n");
+ }
+ else
+ {
+ LOG_FMT(log, "Text() is '%s', type is %s,\n", chunk->Text(), get_token_name(chunk->GetType()));
+ }
+}
+
+
+static void chunk_log(Chunk *pc, const char *text)
+{
+ if ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && (cpd.unc_stage != unc_stage_e::TOKENIZE)
+ && (cpd.unc_stage != unc_stage_e::CLEANUP))
+ {
+ const log_sev_t log = LCHUNK;
+ Chunk *prev = pc->GetPrev();
+ Chunk *next = pc->GetNext();
+
+ chunk_log_msg(pc, log, text);
+
+ if ( prev->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ chunk_log_msg(prev, log, " @ between");
+ chunk_log_msg(next, log, " and");
+ }
+ else if (next->IsNotNullChunk())
+ {
+ chunk_log_msg(next, log, " @ before");
+ }
+ else if (prev->IsNotNullChunk())
+ {
+ chunk_log_msg(prev, log, " @ after");
+ }
+ LOG_FMT(log, " stage is %s", // Issue #3034
+ get_unc_stage_name(cpd.unc_stage));
+ log_func_stack_inline(log);
+ }
+}
+
+
+void Chunk::Delete(Chunk * &pc)
+{
+ gChunkList.Remove(pc);
+ delete pc;
+ pc = Chunk::NullChunkPtr;
+}
+
+
+void Chunk::MoveAfter(Chunk *ref)
+{
+ LOG_FUNC_ENTRY();
+
+ if (ref == this)
+ {
+ return;
+ }
+ gChunkList.Remove(this);
+ gChunkList.AddAfter(this, ref);
+
+ // Adjust the original column
+ m_column = ref->m_column + space_col_align(ref, this);
+ m_origCol = m_column;
+ m_origColEnd = m_origCol + Len();
+}
+
+
+void Chunk::Swap(Chunk *other)
+{
+ gChunkList.Swap(this, other);
+}
+
+
+bool Chunk::IsAddress() const
+{
+ if ( IsNotNullChunk()
+ && ( Is(CT_BYREF)
+ || ( Len() == 1
+ && m_str[0] == '&'
+ && IsNot(CT_OPERATOR_VAL))))
+ {
+ Chunk *prevc = GetPrev();
+
+ if ( TestFlags(PCF_IN_TEMPLATE)
+ && ( prevc->Is(CT_COMMA)
+ || prevc->Is(CT_ANGLE_OPEN)))
+ {
+ return(false);
+ }
+ return(true);
+ }
+ return(false);
+}
+
+
+Chunk *Chunk::GetFirstChunkOnLine() const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+ Chunk *first = pc;
+
+ pc = pc->GetPrev();
+
+ while ( pc->IsNotNullChunk()
+ && !pc->IsNewline())
+ {
+ first = pc;
+ pc = pc->GetPrev();
+ }
+ return(first);
+}
+
+
+bool Chunk::IsLastChunkOnLine() const
+{
+ if (this == Chunk::GetTail())
+ {
+ return(true);
+ }
+
+ // if the next chunk is a newline then pc is the last chunk on its line
+ if (GetNext()->Is(CT_NEWLINE))
+ {
+ return(true);
+ }
+ return(false);
+}
+
+
+void Chunk::SwapLines(Chunk *other)
+{
+ // to swap lines we need to find the first chunk of the lines
+ Chunk *pc1 = GetFirstChunkOnLine();
+ Chunk *pc2 = other->GetFirstChunkOnLine();
+
+ if ( pc1->IsNullChunk()
+ || pc2->IsNullChunk()
+ || pc1 == pc2)
+ {
+ return;
+ }
+ /*
+ * Example start:
+ * ? - start1 - a1 - b1 - nl1 - ? - ref2 - start2 - a2 - b2 - nl2 - ?
+ * ^- pc1 ^- pc2
+ */
+ Chunk *ref2 = pc2->GetPrev();
+
+ // Move the line started at pc2 before pc1
+ while ( pc2->IsNotNullChunk()
+ && !pc2->IsNewline())
+ {
+ Chunk *tmp = pc2->GetNext();
+ gChunkList.Remove(pc2);
+ gChunkList.AddBefore(pc2, pc1);
+ pc2 = tmp;
+ }
+ /*
+ * Should now be:
+ * ? - start2 - a2 - b2 - start1 - a1 - b1 - nl1 - ? - ref2 - nl2 - ?
+ * ^- pc1 ^- pc2
+ */
+
+ // Now move the line started at pc1 after ref2
+ while ( pc1->IsNotNullChunk()
+ && !pc1->IsNewline())
+ {
+ Chunk *tmp = pc1->GetNext();
+ gChunkList.Remove(pc1);
+
+ if (ref2->IsNotNullChunk())
+ {
+ gChunkList.AddAfter(pc1, ref2);
+ }
+ else
+ {
+ gChunkList.AddHead(pc1);
+ }
+ ref2 = pc1;
+ pc1 = tmp;
+ }
+ /*
+ * Should now be:
+ * ? - start2 - a2 - b2 - nl1 - ? - ref2 - start1 - a1 - b1 - nl2 - ?
+ * ^- pc1 ^- pc2
+ */
+
+ /*
+ * pc1 and pc2 should be the newlines for their lines.
+ * swap the chunks and the new line count so that the spacing remains the same.
+ */
+ if ( pc1->IsNotNullChunk()
+ && pc2->IsNotNullChunk())
+ {
+ size_t nlCount = pc1->GetNlCount();
+
+ pc1->SetNlCount(pc2->GetNlCount());
+ pc2->SetNlCount(nlCount);
+
+ pc1->Swap(pc2);
+ }
+} // Chunk::SwapLines
+
+
+void Chunk::SetResetFlags(T_PcfFlags resetBits, T_PcfFlags setBits)
+{
+ if (IsNotNullChunk())
+ {
+ LOG_FUNC_ENTRY();
+ const T_PcfFlags newFlags = (m_flags & ~resetBits) | setBits;
+
+ if (m_flags != newFlags)
+ {
+ LOG_FMT(LSETFLG,
+ "%s(%d): %016llx^%016llx=%016llx\n"
+ "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s', type is %s,",
+ __func__, __LINE__,
+ static_cast<T_PcfFlags::int_t>(m_flags),
+ static_cast<T_PcfFlags::int_t>(m_flags ^ newFlags),
+ static_cast<T_PcfFlags::int_t>(newFlags),
+ __func__, __LINE__, m_origLine, m_origCol, Text(), get_token_name(m_type));
+ LOG_FMT(LSETFLG, " parent type is %s,\n",
+ get_token_name(m_parentType));
+ log_func_stack_inline(LSETFLG);
+
+ LOG_FMT(LSETFLG, " before: ");
+ log_pcf_flags(LSETFLG, m_flags);
+ LOG_FMT(LSETFLG, " after: ");
+ log_pcf_flags(LSETFLG, newFlags);
+ m_flags = newFlags;
+ }
+ }
+}
+
+
+void Chunk::SetTypeReal(const E_Token token, const char *func, const int line)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( IsNullChunk()
+ || m_type == token)
+ {
+ return;
+ }
+ LOG_FMT(LSETTYP, "%s(%d): orig line is %zu, orig col is %zu, Text() is ",
+ func, line, m_origLine, m_origCol);
+
+ if (token == CT_NEWLINE)
+ {
+ LOG_FMT(LSETTYP, "<Newline>\n");
+ }
+ else
+ {
+ LOG_FMT(LSETTYP, "'%s'\n", Text());
+ }
+ LOG_FMT(LSETTYP, " type is %s, parent type is %s => new type is %s\n",
+ get_token_name(m_type), get_token_name(m_parentType), get_token_name(token));
+ m_type = token;
+}
+
+
+void Chunk::SetParentTypeReal(const E_Token token, const char *func, const int line)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( IsNullChunk()
+ || m_parentType == token)
+ {
+ return;
+ }
+ LOG_FMT(LSETPAR, "%s(%d): orig line is %zu, orig col is %zu, Text() is ",
+ func, line, m_origLine, m_origCol);
+
+ if (token == CT_NEWLINE)
+ {
+ LOG_FMT(LSETPAR, "<Newline>\n");
+ }
+ else
+ {
+ LOG_FMT(LSETPAR, "'%s'\n", Text());
+ }
+ LOG_FMT(LSETPAR, " type is %s, parent type is %s => new parent type is %s\n",
+ get_token_name(m_type), get_token_name(m_parentType), get_token_name(token));
+ m_parentType = token;
+}
+
+
+Chunk *Chunk::CopyAndAdd(Chunk *pos, const E_Direction dir) const
+{
+#ifdef DEBUG
+ // test if this chunk is properly set
+ if (m_ppLevel == 999)
+ {
+ fprintf(stderr, "%s(%d): pp level is not set\n", __func__, __LINE__);
+ log_func_stack_inline(LSETFLG);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+
+ if (m_origLine == 0)
+ {
+ fprintf(stderr, "%s(%d): no line number\n", __func__, __LINE__);
+ log_func_stack_inline(LSETFLG);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+
+ if (m_origCol == 0)
+ {
+ fprintf(stderr, "%s(%d): no column number\n", __func__, __LINE__);
+ log_func_stack_inline(LSETFLG);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+#endif /* DEBUG */
+
+ Chunk *pc = new Chunk(*this);
+
+ if ( pos != nullptr
+ && pos->IsNotNullChunk())
+ {
+ (dir == E_Direction::FORWARD) ? gChunkList.AddAfter(pc, pos) : gChunkList.AddBefore(pc, pos);
+ }
+ else
+ {
+ (dir == E_Direction::FORWARD) ? gChunkList.AddHead(pc) : gChunkList.AddTail(pc);
+ }
+ chunk_log(pc, "CopyAndAdd(A):");
+ return(pc);
+} // Chunk::CopyAndAdd
+
+
+Chunk *Chunk::GetNextNbsb() const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while ( pc->Is(CT_TSQUARE)
+ || pc->Is(CT_SQUARE_OPEN))
+ {
+ if (pc->Is(CT_SQUARE_OPEN))
+ {
+ pc = pc->GetClosingParen();
+ }
+ pc = pc->GetNextNcNnl();
+ }
+ return(pc);
+}
+
+
+Chunk *Chunk::GetPrevNbsb() const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while ( pc->Is(CT_TSQUARE)
+ || pc->Is(CT_SQUARE_CLOSE))
+ {
+ if (pc->Is(CT_SQUARE_CLOSE))
+ {
+ pc = pc->GetOpeningParen();
+ }
+ pc = pc->GetPrevNcNnl();
+ }
+ return(pc);
+}
+
+
+Chunk *Chunk::GetPpStart() const
+{
+ if (!IsPreproc())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while (pc->IsNot(CT_PREPROC))
+ {
+ pc = pc->GetPrev(E_Scope::PREPROC);
+ }
+ return(pc);
+}
+
+
+Chunk *Chunk::SkipDcMember() const
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = const_cast<Chunk *>(this);
+ Chunk *nxt = pc->Is(CT_DC_MEMBER) ? pc : pc->GetNextNcNnl(E_Scope::ALL);
+
+ while (nxt->Is(CT_DC_MEMBER))
+ {
+ pc = nxt->GetNextNcNnl(E_Scope::ALL);
+
+ if (pc->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ nxt = pc->GetNextNcNnl(E_Scope::ALL);
+ }
+ return(pc);
+}
+
+
+int Chunk::ComparePosition(const Chunk *other) const
+{
+ if (m_origLine < other->m_origLine)
+ {
+ return(-1);
+ }
+ else if (m_origLine == other->m_origLine)
+ {
+ if (m_origCol < other->m_origCol)
+ {
+ return(-1);
+ }
+ else if (m_origCol == other->m_origCol)
+ {
+ return(0);
+ }
+ }
+ return(1);
+}
+
+
+bool Chunk::IsOCForinOpenParen() const
+{
+ if ( language_is_set(LANG_OC)
+ && Is(CT_SPAREN_OPEN)
+ && GetPrevNcNnl()->Is(CT_FOR))
+ {
+ Chunk *nxt = const_cast<Chunk *>(this);
+
+ while ( nxt->IsNotNullChunk()
+ && nxt->IsNot(CT_SPAREN_CLOSE)
+ && nxt->IsNot(CT_IN))
+ {
+ nxt = nxt->GetNextNcNnl();
+ }
+
+ if (nxt->Is(CT_IN))
+ {
+ return(true);
+ }
+ }
+ return(false);
+}
+
+
+bool Chunk::IsStringAndLevel(const char *cStr, const size_t len,
+ bool caseSensitive, const int level) const
+{
+ return( ( level < 0
+ || m_level == static_cast<size_t>(level))
+ && Len() == len // the length is as expected
+ && ( ( caseSensitive
+ && memcmp(Text(), cStr, len) == 0)
+ || ( !caseSensitive
+ && strncasecmp(Text(), cStr, len) == 0))); // the strings are equal
+}
+
+
+Chunk *Chunk::GetClosingParen(E_Scope scope) const
+{
+ if ( Is(CT_PAREN_OPEN)
+ || Is(CT_SPAREN_OPEN)
+ || Is(CT_FPAREN_OPEN)
+ || Is(CT_TPAREN_OPEN)
+ || Is(CT_BRACE_OPEN)
+ || Is(CT_VBRACE_OPEN)
+ || Is(CT_ANGLE_OPEN)
+ || Is(CT_SQUARE_OPEN))
+ {
+ return(GetNextType((E_Token)(m_type + 1), m_level, scope));
+ }
+ return(const_cast<Chunk *>(this));
+}
+
+
+Chunk *Chunk::GetOpeningParen(E_Scope scope) const
+{
+ if ( Is(CT_PAREN_CLOSE)
+ || Is(CT_SPAREN_CLOSE)
+ || Is(CT_FPAREN_CLOSE)
+ || Is(CT_TPAREN_CLOSE)
+ || Is(CT_BRACE_CLOSE)
+ || Is(CT_VBRACE_CLOSE)
+ || Is(CT_ANGLE_CLOSE)
+ || Is(CT_SQUARE_CLOSE))
+ {
+ return(GetPrevType((E_Token)(m_type - 1), m_level, scope));
+ }
+ return(const_cast<Chunk *>(this));
+}
+
+
+bool Chunk::IsCppInheritanceAccessSpecifier() const
+{
+ return( language_is_set(LANG_CPP)
+ && ( Is(CT_ACCESS)
+ || Is(CT_QUALIFIER))
+ && ( IsString("private")
+ || IsString("protected")
+ || IsString("public")));
+}
+
+
+bool Chunk::IsColon() const
+{
+ return( Is(CT_ACCESS_COLON)
+ || Is(CT_ASM_COLON)
+ || Is(CT_BIT_COLON)
+ || Is(CT_CASE_COLON)
+ || Is(CT_CLASS_COLON)
+ || Is(CT_COLON)
+ || Is(CT_COND_COLON)
+ || Is(CT_CONSTR_COLON)
+ || Is(CT_CS_SQ_COLON)
+ || Is(CT_D_ARRAY_COLON)
+ || Is(CT_FOR_COLON)
+ || Is(CT_LABEL_COLON)
+ || Is(CT_OC_COLON)
+ || Is(CT_OC_DICT_COLON)
+ || Is(CT_TAG_COLON)
+ || Is(CT_WHERE_COLON));
+}
+
+
+bool Chunk::IsDoxygenComment() const
+{
+ if (!IsComment())
+ {
+ return(false);
+ }
+
+ if (Len() < 3)
+ {
+ return(false);
+ }
+ // check the third character
+ const char *sComment = Text();
+ return( (sComment[2] == '/')
+ || (sComment[2] == '!')
+ || (sComment[2] == '@'));
+}
+
+
+bool Chunk::IsTypeDefinition() const
+{
+ return( Is(CT_TYPE)
+ || Is(CT_PTR_TYPE)
+ || Is(CT_BYREF)
+ || Is(CT_DC_MEMBER)
+ || Is(CT_QUALIFIER)
+ || Is(CT_STRUCT)
+ || Is(CT_ENUM)
+ || Is(CT_UNION));
+}
+
+
+bool Chunk::IsNewlineBetween(const Chunk *other) const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while (pc != other)
+ {
+ if (pc->IsNewline())
+ {
+ return(true);
+ }
+ pc = pc->GetNext();
+ }
+ return(false);
+}