diff --git a/bin/assets/plugins/linters.json b/bin/assets/plugins/linters.json index 13bc54f15..d9e99ec71 100644 --- a/bin/assets/plugins/linters.json +++ b/bin/assets/plugins/linters.json @@ -14,13 +14,10 @@ { "language": "json", "file_patterns": ["%.json$"], - "warning_pattern": "parse%s(%w*):%s(.*)at%sline%s(%d*),%scolumn%s(%d*)", - "warning_pattern_order": { "line": 3, "col": 4, "message": 2, "type": 1 }, - "command": "jq -e . $FILENAME", - "expected_exitcodes": [1, 2, 3, 4, 5], - "no_errors_exit_code": 0, - "use_tmp_folder": true, - "url": "https://stedolan.github.io/jq/" + "warning_pattern": "", + "command": "json", + "type": "native", + "url": "#native" }, { "language": ["javascript", "typescript", "jsx", "tsx"], diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 01e88ccf1..4f3950fef 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -810,13 +810,15 @@ void LinterPlugin::lintDoc( std::shared_ptr doc ) { if ( linter.command.empty() ) return; - bool binaryFound = false; - auto parts = String::split( linter.command, ' ' ); - if ( !parts.empty() ) { - if ( parts[0].find_first_of( "\\/" ) != std::string::npos ) { - binaryFound = FileSystem::fileExists( parts[0] ); - } else { - binaryFound = !Sys::which( parts[0] ).empty(); + bool binaryFound = linter.isNative; + if ( !linter.isNative ) { + auto parts = String::split( linter.command, ' ' ); + if ( !parts.empty() ) { + if ( parts[0].find_first_of( "\\/" ) != std::string::npos ) { + binaryFound = FileSystem::fileExists( parts[0] ); + } else { + binaryFound = !Sys::which( parts[0] ).empty(); + } } } if ( !binaryFound ) @@ -855,15 +857,15 @@ void LinterPlugin::lintDoc( std::shared_ptr doc ) { void LinterPlugin::runLinter( std::shared_ptr doc, const Linter& linter, const std::string& path ) { std::string cmd( linter.command ); + if ( linter.isNative && mNativeLinters.find( cmd ) != mNativeLinters.end() ) { + mNativeLinters[cmd]( doc, path ); + return; + } std::string pathstr( "\"" + path + "\"" ); String::replaceAll( cmd, "$FILENAME", pathstr ); String::replaceAll( cmd, "${file_path}", pathstr ); String::replaceAll( cmd, "$PROJECTPATH", mManager->getWorkspaceFolder() ); String::replaceAll( cmd, "${project_root}", mManager->getWorkspaceFolder() ); - if ( linter.isNative && mNativeLinters.find( cmd ) != mNativeLinters.end() ) { - mNativeLinters[cmd]( doc, path ); - return; - } std::unique_ptr process = std::make_unique(); TextDocument* docPtr = doc.get(); ScopedOp op( @@ -1539,6 +1541,45 @@ void LinterPlugin::registerNativeLinters() { } setMatches( doc.get(), MatchOrigin::Linter, matches ); }; + + mNativeLinters["json"] = [this]( std::shared_ptr doc, const std::string& path ) { + std::map> ret; + + std::string file; + FileSystem::fileGet( path, file ); + + json j; + try { + j = json::parse( file, nullptr, true, true ); + } catch ( const json::exception& e ) { + LuaPattern ptrn( "line%s(%d+),%scolumn%s(%d+)" ); + PatternMatcher::Range matches[4]; + std::string_view err( e.what() ); + if ( ptrn.matches( err.data(), matches ) ) { + auto lineStr( err.substr( matches[1].start, matches[1].end - matches[1].start ) ); + auto offsetStr( err.substr( matches[2].start, matches[2].end - matches[2].start ) ); + Int64 line; + Int64 offset; + String::fromString( line, lineStr ); + String::fromString( offset, offsetStr ); + if ( line ) + line--; + LinterMatch match; + match.range = { { line, offset }, { line, offset } }; + match.range = { doc->nextWordBoundary( match.range.start(), false ), + doc->previousWordBoundary( match.range.start(), false ) }; + if ( !match.range.hasSelection() ) + match.range.setEnd( { line, offset + 1 } ); + match.text = err; + match.type = getLinterTypeFromSeverity( LSPDiagnosticSeverity::Error ); + match.lineHash = doc->getLineHash( match.range.start().line() ); + match.origin = MatchOrigin::Linter; + ret[line] = { match }; + } + } + + setMatches( doc.get(), MatchOrigin::Linter, ret ); + }; } } // namespace ecode