1+ // `yaml` is not type safe 🤷♂️
2+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3+ /* eslint-disable @typescript-eslint/no-explicit-any */
4+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
15import { Injectable , InternalServerErrorException } from '@nestjs/common' ;
26import child_process from 'child_process' ;
37import fs from 'fs' ;
48import * as uuid from 'uuid' ;
9+ import YAML from 'yaml' ;
510import { ConvertToGolangCILintOutput } from './linters/golangcilint' ;
611import { ConvertToPylintOutput } from './linters/pylint' ;
712
@@ -26,7 +31,24 @@ export class LintService {
2631 output = output . substring ( 0 , output . length - 1 ) ;
2732 const pylintOutput = ConvertToPylintOutput . toPylintOutput ( output ) ;
2833 if ( pylintOutput ) {
29- // Remove one point to the score per violation
34+ /*
35+ Example output:
36+ [
37+ {
38+ "type": "convention",
39+ "module": "fib",
40+ "obj": "",
41+ "line": 1,
42+ "column": 0,
43+ "path": "fib.py",
44+ "symbol": "missing-module-docstring",
45+ "message": "Missing module docstring",
46+ "message-id": "C0114"
47+ },
48+ ...
49+
50+ Remove one point to the score per violation
51+ */
3052 return 100 - pylintOutput . length ;
3153 }
3254 } catch ( e ) {
@@ -63,6 +85,31 @@ export class LintService {
6385 const lintOuput =
6486 ConvertToGolangCILintOutput . toGolangCILintOutput ( output ) ;
6587 if ( lintOuput ) {
88+ /*
89+ Example output:
90+
91+ {
92+ "Issues": [
93+ {
94+ "FromLinter": "errcheck",
95+ "Text": "Error return value of `http.ListenAndServe` is not checked",
96+ "Severity": "",
97+ "SourceLines": [
98+ "\thttp.ListenAndServe(\":9567\", nil)"
99+ ],
100+ "Replacement": null,
101+ "Pos": {
102+ "Filename": "http.go",
103+ "Offset": 417,
104+ "Line": 27,
105+ "Column": 21
106+ },
107+ "ExpectNoLint": false,
108+ "ExpectedNoLintLinter": ""
109+ }
110+ ],
111+ ...
112+ */
66113 if ( lintOuput . issues ) {
67114 // Remove one point to the score per violation
68115 return 100 - lintOuput . issues . length ;
@@ -76,4 +123,56 @@ export class LintService {
76123
77124 throw new InternalServerErrorException ( ) ;
78125 }
126+
127+ lintCpp ( code : string ) : number {
128+ // clang-tidy doesn't support stdin
129+ const path = `/tmp/codebench_${ uuid . v4 ( ) } .cpp` ;
130+ const outputPath = `${ path } .yaml` ;
131+ try {
132+ fs . writeFileSync ( path , code ) ;
133+ } catch ( e ) {
134+ throw new InternalServerErrorException ( e ) ;
135+ }
136+
137+ const result = child_process . spawnSync ( 'clang-tidy' , [
138+ `-export-fixes=${ outputPath } ` ,
139+ path ,
140+ '--' ,
141+ '-Wall' ,
142+ '-std=c++11' ,
143+ '-x' ,
144+ 'c++' ,
145+ ] ) ;
146+
147+ if ( result . error ) {
148+ throw new InternalServerErrorException ( result . error ) ;
149+ }
150+
151+ try {
152+ if ( fs . existsSync ( outputPath ) ) {
153+ const file = fs . readFileSync ( `${ path } .yaml` , 'utf8' ) ;
154+ const fixes : any = YAML . parse ( file ) ;
155+ if ( fixes ) {
156+ /*
157+ Example file:
158+ ---
159+ MainSourceFile: /root/fib.cpp
160+ Diagnostics:
161+ - DiagnosticName: clang-diagnostic-unused-variable
162+ Message: 'unused variable ''d'''
163+ FileOffset: 142
164+ FilePath: /root/fib.cpp
165+ Replacements:
166+ ...
167+ */
168+ if ( fixes . Diagnostics ) {
169+ return 100 - fixes . Diagnostics . length ;
170+ }
171+ }
172+ }
173+ return 100 ;
174+ } catch ( e ) {
175+ throw new InternalServerErrorException ( e ) ;
176+ }
177+ }
79178}
0 commit comments