summaryrefslogtreecommitdiffstats
path: root/languages/cpp/completiondebug.h
blob: 7582329616ad0582ae2b8ee4ca43bef4b1488b38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/***************************************************************************
copyright            : (C) 2006 by David Nolden
email                : david.nolden.tdevelop@art-master.de
***************************************************************************/
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef __COMPLETIONDEBUG_H__
#define __COMPLETIONDEBUG_H__

///With verbose shut on, the whole type-resolution-process is nicely traced for easy debugging(at cost of speed).
//#define VERBOSE
//#define VERBOSEMAJOR

///When defined, a backtrace is printed the first time the maximum depth is reached for the first time.
//#define DEPTHBACKTRACE

#include <tqstringlist.h>
#include <kdebug.h>

namespace CompletionDebug {
template <class StreamType>
class KDDebugState {
  private:
    StreamType m_stream;
    kndbgstream m_nstream;
    TQStringList m_prefixStack;
    int m_counter;
    int m_depth;
    bool m_enabled;
		bool m_hadWarning;

  public:
    typedef StreamType KStreamType;
    KDDebugState();

		KDDebugState( StreamType stream ) : m_stream( stream ), m_counter( 0 ), m_depth( 0 ), m_enabled( true ), m_hadWarning( false ) {}

    void push( const TQString & txt ) {
      m_prefixStack.push_back( txt );
      pushDepth();
    }

    void pop() {
      m_prefixStack.pop_back();
      popDepth();
    };

    inline void pushDepth() {
      m_depth++;
    }

    inline void popDepth() {
      m_depth--;
    }

		bool hadWarning() {
			return m_hadWarning;
		}

		void setHadWarning( bool had ) {
			m_hadWarning = had;
		}

    StreamType& dbg() {
#ifndef VERBOSE
      if ( !m_enabled )
        return m_nstream;
#endif

      m_stream << "(" << m_counter << ")";
      for ( TQStringList::iterator it = m_prefixStack.begin(); it != m_prefixStack.end() ; ++it )
        m_stream << *it;

      m_counter++;
      return m_stream;
    }

    void setState( bool enabled ) {
      m_enabled = enabled;
    }

    bool state() {
      return m_enabled;
    }

#ifndef NDEBUG
    void outputPrefix( kdbgstream& target ) {
      target << "(" << m_counter << ")";
      for ( TQStringList::iterator it = m_prefixStack.begin(); it != m_prefixStack.end() ; ++it )
        target << *it;

      m_counter++;
    }
#endif

    void clearCounter() {
      m_counter = 0;
    }

    int depth() {
      return m_depth;
    }
};
#ifndef NDEBUG
template <>
KDDebugState<kdbgstream>::KDDebugState();
#endif
template <>
KDDebugState<kndbgstream>::KDDebugState();
#if defined(VERBOSE) && !defined(NDEBUG)
typedef KDDebugState<kdbgstream> DBGStreamType;
#else
typedef KDDebugState<kndbgstream> DBGStreamType;
#endif
///Class to help indent the debug-output correctly
extern DBGStreamType dbgState;
extern const int completionMaxDepth;
class LogDebug {
  private:
    DBGStreamType& m_state;
    int m_max;
  public:
    LogDebug( const char* prefix = "#", int max = completionMaxDepth, DBGStreamType& st = dbgState ) : m_state( st ), m_max( max ) {
      m_state.push( prefix );
    };
    ~LogDebug() {
      m_state.pop();
    }

    DBGStreamType::KStreamType& dbg() {
      return m_state.dbg();
    }

    int depth() {
      return m_state.depth();
    }

    operator bool() {
      bool r = depth() < m_max;

	    if ( !r && !m_state.hadWarning() ) {
		    m_state.setHadWarning( true );
		    dbg() << "recursion is too deep" << endl;
#ifdef DEPTHBACKTRACE
        kdDebug( 9007 ) << kdBacktrace() << endl;
#endif
      }
      return r;
    }
};


///does not care about the logging, but still counts the depth
class DepthDebug {
    DBGStreamType& m_state;
    int m_max;
  public:
    DepthDebug( const char* prefix = "#", int max = completionMaxDepth, DBGStreamType& st = dbgState ) : m_state( st ), m_max( max ) {
      Q_UNUSED( prefix );
      m_state.pushDepth();
    };

    ~DepthDebug() {
      m_state.popDepth();
    }

    kndbgstream dbg() {
      return kndDebug();
    }

    int depth() {
      return m_state.depth();
    }

    operator bool() {
      bool r = depth() < m_max;

	    if ( !r && !m_state.hadWarning() ) {
		    m_state.setHadWarning( true );
		    dbg() << "recursion is too deep" << endl;
#ifdef DEPTHBACKTRACE
		    kdDebug( 9007 ) << kdBacktrace() << endl;
#endif
	    }
	    return r;
    }
};

#ifndef VERBOSEMAJOR
#define ifVerboseMajor(x) /**/
#else
#define ifVerboseMajor(x) x
#endif

bool dbgActive();

#ifdef VERBOSE

typedef LogDebug Debug;
DBGStreamType::KStreamType& dbg();
#define ifVerbose( x) {if( dbgActive() ) {x;}}
#else

DBGStreamType::KStreamType& dbg();
typedef DepthDebug Debug;
#define ifVerbose(x) /**/
#endif
#ifndef NDEBUG
kdbgstream dbgMajor();
#else
kndbgstream dbgMajor();
#endif
}
#endif
// kate: indent-mode csands; tab-width 2;