1717
1818package com .duy .ccppcompiler .compiler .analyze ;
1919
20+ import android .annotation .SuppressLint ;
2021import android .content .Context ;
22+ import android .core .widget .EditAreaView ;
23+ import android .os .AsyncTask ;
2124import android .os .Handler ;
2225import android .support .annotation .NonNull ;
2326import android .text .Editable ;
2427import android .text .TextWatcher ;
2528
2629import com .duy .ccppcompiler .compiler .shell .CommandBuilder ;
2730import com .duy .ccppcompiler .compiler .shell .CommandResult ;
28- import com .duy .ccppcompiler .compiler .shell .OutputParser ;
2931import com .duy .ccppcompiler .compiler .shell .Shell ;
3032import com .duy .common .DLog ;
3133import com .duy .ide .diagnostic .Diagnostic ;
3739import java .io .File ;
3840import java .io .IOException ;
3941import java .util .ArrayList ;
40- import java .util .regex .Pattern ;
4142
4243/**
4344 * https://sourceforge.net/p/cppcheck/wiki/Home/
45+ * <p>
46+ * # enable warning messages
47+ * cppcheck --enable=warning file.c
48+ * <p>
49+ * # enable performance messages
50+ * cppcheck --enable=performance file.c
51+ * <p>
52+ * # enable information messages
53+ * cppcheck --enable=information file.c
54+ * <p>
55+ * # For historical reasons, --enable=style enables warning, performance,
56+ * # portability and style messages. These are all reported as "style" when
57+ * # using the old xml format.
58+ * cppcheck --enable=style file.c
59+ * <p>
60+ * # enable warning and performance messages
61+ * cppcheck --enable=warning,performance file.c
62+ * <p>
63+ * # enable unusedFunction checking. This is not enabled by --enable=style
64+ * # because it doesn't work well on libraries.
65+ * cppcheck --enable=unusedFunction file.c
66+ * <p>
67+ * # enable all messages
68+ * cppcheck --enable=all
4469 */
4570public class CppCheckAnalyzer implements ICodeAnalyser {
4671 public static final long DELAY_TIME = 300 ;
4772 private static final String TAG = "CppCheckAnalyzer" ;
4873
4974 private static final String CPPCHECK_PROGRAM = "cppcheck" ;
50- private static final String TEMPLATE = "--template=\" {file}:{line}:{message}\" " ;
51- private static final Pattern TEMPLATE_PATTERN = Pattern .compile ("^(\\ S+):([0-9]+):(.*)" );
5275
5376 private final Context mContext ;
5477 private final IEditorDelegate mEditorDelegate ;
5578 private final android .os .Handler mHandler = new Handler ();
5679 private DiagnosticPresenter mDiagnosticPresenter ;
80+ private AnalyzeTask mAnalyzeTask ;
5781 private final Runnable mAnalyze = new Runnable () {
5882 @ Override
5983 public void run () {
@@ -72,37 +96,14 @@ public CppCheckAnalyzer(@NonNull Context context, @NonNull IEditorDelegate deleg
7296 }
7397
7498 private void analyzeImpl () throws IOException {
75- File originFile = mEditorDelegate .getDocument ().getFile ();
76- File tmpFile = new File (getCppCheckTmpDir (), originFile .getName ());
77-
78- LocalFileWriter localFileWriter = new LocalFileWriter (tmpFile , "UTF-8" );
79- localFileWriter .writeToFile (mEditorDelegate .getEditText ().getText ());
80-
81- CommandBuilder builder = new CommandBuilder (CPPCHECK_PROGRAM );
82- builder .addFlags (TEMPLATE );
83- builder .addFlags (tmpFile .getAbsolutePath ());
84-
85- String cmd = builder .build ();
86- CommandResult result = Shell .exec (mContext , tmpFile .getParent (), cmd );
87- if (DLog .DEBUG ) DLog .d (TAG , "result = " + result );
88- String message = result .getMessage ().replace (tmpFile .getAbsolutePath (), originFile .getAbsolutePath ());
89-
90- DiagnosticsCollector diagnosticsCollector = new DiagnosticsCollector ();
91- OutputParser parser = new OutputParser (diagnosticsCollector );
92- parser .parse (message );
93-
94- ArrayList <Diagnostic > diagnostics = diagnosticsCollector .getDiagnostics ();
95- mDiagnosticPresenter .setDiagnostics (diagnostics );
96- }
97-
98- private File getCppCheckTmpDir () {
99- File dir = new File (mContext .getCacheDir (), "cppcheck/tmp" );
100- if (!dir .exists ()) {
101- dir .mkdirs ();
99+ if (mAnalyzeTask != null ) {
100+ mAnalyzeTask .cancel (true );
102101 }
103- return dir ;
102+ mAnalyzeTask = new AnalyzeTask (mContext , mEditorDelegate , mDiagnosticPresenter );
103+ mAnalyzeTask .execute ();
104104 }
105105
106+
106107 @ Override
107108 public void start () {
108109 mEditorDelegate .getEditText ().addTextChangedListener (new TextWatcher () {
@@ -124,4 +125,69 @@ public void afterTextChanged(Editable s) {
124125 }
125126 });
126127 }
128+
129+ @ SuppressLint ("StaticFieldLeak" )
130+ private static class AnalyzeTask extends AsyncTask <Void , Void , ArrayList <Diagnostic >> {
131+
132+ private final Context mContext ;
133+ private final DiagnosticPresenter mDiagnosticPresenter ;
134+ private IEditorDelegate mEditorDelegate ;
135+
136+ public AnalyzeTask (Context mContext , IEditorDelegate delegate , DiagnosticPresenter mDiagnosticPresenter ) {
137+ this .mContext = mContext ;
138+ this .mEditorDelegate = delegate ;
139+ this .mDiagnosticPresenter = mDiagnosticPresenter ;
140+ }
141+
142+ @ Override
143+ protected ArrayList <Diagnostic > doInBackground (Void ... voids ) {
144+ EditAreaView editText = mEditorDelegate .getEditText ();
145+
146+ File originFile = mEditorDelegate .getDocument ().getFile ();
147+ File tmpFile = new File (getCppCheckTmpDir (), originFile .getName ());
148+
149+ LocalFileWriter localFileWriter = new LocalFileWriter (tmpFile , "UTF-8" );
150+ try {
151+ localFileWriter .writeToFile (editText .getText ());
152+ } catch (IOException e ) {
153+ e .printStackTrace ();
154+ return null ;
155+ }
156+
157+ CommandBuilder builder = new CommandBuilder (CPPCHECK_PROGRAM );
158+ builder .addFlags (CppCheckOutputParser .TEMPLATE );
159+ builder .addFlags (tmpFile .getAbsolutePath ());
160+ builder .addFlags ("--enable=warning,performance,information" );
161+
162+ String cmd = builder .build ();
163+ CommandResult result = Shell .exec (mContext , tmpFile .getParent (), cmd );
164+ if (isCancelled ()) {
165+ return null ;
166+ }
167+
168+ if (DLog .DEBUG ) DLog .d (TAG , "result = " + result );
169+ String message = result .getMessage ().replace (tmpFile .getAbsolutePath (), originFile .getAbsolutePath ());
170+ DiagnosticsCollector diagnosticsCollector = new DiagnosticsCollector ();
171+ CppCheckOutputParser parser = new CppCheckOutputParser (diagnosticsCollector );
172+ parser .parse (message );
173+
174+ return diagnosticsCollector .getDiagnostics ();
175+ }
176+
177+ private File getCppCheckTmpDir () {
178+ File dir = new File (mContext .getCacheDir (), "cppcheck/tmp" );
179+ if (!dir .exists ()) {
180+ dir .mkdirs ();
181+ }
182+ return dir ;
183+ }
184+
185+ @ Override
186+ protected void onPostExecute (ArrayList <Diagnostic > diagnostics ) {
187+ super .onPostExecute (diagnostics );
188+ if (diagnostics != null && !isCancelled ()) {
189+ mDiagnosticPresenter .setDiagnostics (diagnostics );
190+ }
191+ }
192+ }
127193}
0 commit comments