资讯动态

JPlag 支持的语言全景:模块体系、成熟度标签与语言模块加载机制

发布时间:2026/10/14 16:34:22 来源:尧图企业网站定制
代码质量教育后端【免费下载链接】JPlagState-of-the-Art Source Code Plagiarism Collusion Detection. Check for plagiarism in a set of programs.项目地址https://gitcode.com/gh_mirrors/jp/JPlag点击查看免费下载JPlag 是一款本地运行的源代码抄袭与串通检测工具其多语言能力通过一组可插拔的语言模块实现。本文基于 JPlag 仓库中的 支持语言文档 展开结合languages/目录下的 20 余个语言模块源码、Language 接口 与 LanguageLoader 的加载实现系统梳理JPlag 当前支持哪些语言及其版本、各模块成熟度标签mature/beta/alpha/legacy/unknown的确切含义、语言模块必须遵守的接口契约文件后缀、最小匹配 token 数、语义信息、归一化等以及 CLI 子命令如何动态发现并调用语言模块。读完后你可以准确为不同语言的提交集选择合适的检测模块并理解新增语言模块的接入方式。一、当前支持的语言清单根据 README 的 Supported Languages 表格JPlag 支持的完整语言清单、对应语言版本、CLI 参数名、成熟度标签state与所用解析器如下本表继承自 READMECLI 参数名已按源码中的实际 identifier 校准LanguageVersionCLI 参数名stateparserJava25javamatureJavaCC11clegacyJavaCCC14cppmatureANTLR 4C#6csharpmatureANTLR 4Python3.6python3matureANTLR 4JavaScriptES6javascriptbetaANTLR 4TypeScript~5typescriptbetaANTLR 4Go1.17gobetaANTLR 4Kotlin1.3kotlinmatureANTLR 4R3.5.0rlangmatureANTLR 4Rust1.60.0rustmatureANTLR 4Swift5.4swiftbetaANTLR 4Scala2.13.8scalamatureScalametaLLVM IR15llvmirbetaANTLR 4Scheme?schemelegacyJavaCCEMF Metamodel2.25.0emfbetaEMFEMF Model2.25.0emf-modelalphaEMFSCXML1.0scxmlalphaXMLTextnaive, use with caution-textlegacyCoreNLPMulti-Language-multialpha-两点源码层面的补充说明从源码看Go 模块 GoLanguage 的getIdentifier()返回goREADME 的 CLI 帮助列表Languages:小节也以go为准README 表格中golang的写法与当前源码不一致使用时以go为准。languages/目录中还包含一个额外的 Maven 子模块 emf-metamodel-dynamic其 DynamicEmfLanguage 提供基于动态 Ecore 模型的 EMF 检测能力identifier 为emf-dynamic。从源码结构看该模块未标注AutoService因此不会出现在 CLI 的Languages:子命令列表中主要面向 API 集成场景。语言模块的“版本”一列指模块所依据的语法/语言版本并非承诺对更新版本的全量支持运行 JPlag 本身需要 Java SE 25见 README。二、语言模块的成熟度标签state支持语言文档 指出由于各语言模块的年龄与被使用频率不同其成熟度存在差异因此每个前端frontend都被赋予一个 state 标签。这五类标签的定义是选用模块时的第一参考依据mature经过充分验证并且大致与当前语言版本保持同步beta相对较新且大致保持同步但测试覆盖不如 mature 充分欢迎反馈Feedback welcomealpha非常新、尚未完成请谨慎使用Use with cautionlegacy来自 JPlag legacyv3.0.0 之前可能只支持过时的语言版本等待更新unknown该模块处于什么状态尚不明确。对照上表可以看到Java、C、C#、Python、Kotlin、R、Rust、Scala 为 matureJavaScript、TypeScript、Go、Swift、LLVM IR、EMF Metamodel 为 betaEMF Model、SCXML、Multi-Language 为 alphaC、Scheme、Text 为 legacy。例如 C 模块的 README 还特别提示该模块“可能”可以解析 C 提交但应使用 cpp 模块处理 C 代码——这正是 legacy 模块能力边界的典型说明。三、语言模块的源码组织所有语言模块集中在 languages/ 目录由 languages/pom.xml 聚合为 21 个 Maven 子模块c、cpp、csharp、emf-metamodel、emf-metamodel-dynamic、emf-model、golang、java、kotlin、python-3、rlang、rust、scala、scheme、scxml、swift、text、typescript、javascript、llvmir、multi-language。每个模块内部遵循统一结构详见 Adding New Languages 指南组件父类型职责Language 类de.jplag.Language语言模块的访问入口pom.xml-Maven 子模块描述符README.md-模块级文档TokenType 类de.jplag.TokenType语言专属 token 类型Lexer/Parser-源码到 AST 的转换ParserAdapter 类de.jplag.AbstractAntlrParserANTLR 场景装配 Parser 并调用遍历器Traverser/Listener 类-遍历 AST 并生成 token值得注意的核心抽象是JPlag 中的Token 不是词法单元如标识符、关键字而是语法实体如语句、控制结构的表示。例如class MyClass { private String name; }会被表示为CLASS_DECLARATION、CLASS_BODY_BEGIN、FIELD_DECLARATION、CLASS_BODY_END这样的 token 序列——标识符、字面量等语义信息被有意省略从而让比较算法聚焦于代码结构。各模块的完整测试文件如 Complete.go、Complete.R覆盖了目标语言的主要语法元素可用于直观了解各模块的 token 化粒度。四、语言模块的接口契约Language接口每个语言模块必须实现 language-api 中的Language接口。该接口定义了 CLI 与核心比较算法依赖的全部契约关键方法包括方法说明fileExtensions()该语言程序文件的合法扩展名不区分大小写空列表表示接受所有扩展名getName()描述性名称如JavagetIdentifier()用于 CLI 选项与动态加载的短标识符建议符合[a-z_-]minimumTokenMatch()该语言下构成一次匹配所需的最少 token 数默认比较灵敏度基线parse(SetFile, boolean normalize)解析一个提交的全部文件返回 token 列表tokensHaveSemantics()返回的 token 是否携带语义信息supportsNormalization()/requiresCoreNormalization()是否支持 token 序列归一化以及是否使用 core 模块的归一化useViewFiles()/viewFileExtension()报告展示是否使用“视图文件”对输入文件的另一种表示expectsSubmissionOrder()/customizeSubmissionOrder()提交顺序是否影响解析结果supportsMultiLanguage()/hasPriority()能否被 multi 模块复用多模块支持同一扩展名时是否优先getOptions()返回语言专属选项对象供 CLI 子命令展开getCommentExtractorSettings()供注释提取器使用的分隔符配置4.1 各模块的最小匹配 token 数minimumTokenMatchminimumTokenMatch()是每个模块自行声明的“一次匹配至少需要多少 token”。从各语言模块源码可直接读出当前取值模块最小匹配 token 数模块最小匹配 token 数C (c)12Kotlin (kotlin)8C (cpp)12LLVM IR (llvmir)70C# (csharp)8Python 3 (python3)12EMF (emf)6R (rlang)8Go (go)8Rust (rust)8Java (java)9Scala (scala)8SCXML (scxml)6Swift (swift)8Scheme (scheme)13Text (text)5TypeScript (typescript)12JavaScript (javascript)继承 TypeScript12这些默认值可被 CLI 的-t, --min-tokens参数覆盖以调节灵敏度取值过小会增加误报见 README CLI 说明。其中 LLVM IR 高达 70反映了 IR 文本 token 密度高、需要更长片段才算有效匹配的设计取向Text 模块仅 5对应其“naive、谨慎使用”的定位。4.2 文件扩展名与模块间关系各模块声明的扩展名同样决定了 CLI 按什么文件后缀收集提交。几个具有代表性的例子CLanguage 声明.cpp、.cxx、.c、.c、.cc、.h、.hpp、.hh、.hxx——因此 C 模块也能吃掉 C 文件CPPLanguage 声明完全相同的扩展名集合并通过hasPriority()返回true声明“对 C 语言模块拥有优先级”源码注释Priority over the C language module保证 multi 场景下 C 文件优先交给更成熟的 cpp 模块JavaScriptLanguage 直接继承 TypeScriptLanguage仅改写 identifierjavascript、名称与扩展名.js注释明确说明“JavaScript 作为 TypeScript 的一个变体将全部责任委托给 TypeScript 语言模块”NaturalLanguagetext 模块接受.txt、.asc、.tex、.md、.rtf、.csv、.wiki、.json、.yaml、.yml、.xml等大量文本类后缀。此外Java 模块还通过tokensHaveSemantics()与supportsNormalization()返回true表明它返回带语义的 token 并支持 CLI--normalize选项README 说明该选项当前支持 Java 与 CJavaLanguage 还通过getCommentExtractorSettings()提供了字符串分隔符、、、行注释//、块注释/* */与转义符\配置用于注释提取场景。五、语言模块的加载机制与 CLI 集成5.1 ServiceLoader 动态发现语言模块的注册与发现全部基于 Java SPI每个语言类通过AutoService(Language.class)注解编译期生成服务注册文件声明自己是Language实现例如 JavaLanguage 类头的AutoService(Language.class)。LanguageLoader 是发现逻辑的核心for (Language language : ServiceLoader.load(Language.class)) { String languageIdentifier language.getIdentifier(); if (languages.containsKey(languageIdentifier)) { logger.error(Multiple implementations for a language {} are present in the classpath! Skipping .., languageIdentifier); languages.remove(languageIdentifier); continue; } ... languages.put(languageIdentifier, language); }要点通过ServiceLoader.load(Language.class)扫描 classpath 上所有语言实现按getIdentifier()建立映射并缓存getAllAvailableLanguages()若同一 identifier 出现多个实现会记录错误日志并跳过该 identifier避免歧义getLanguage(String identifier)按短名加载单个模块未命中时输出 WARN 日志。这意味着 classpath 中放入了某个语言 jar它就能被识别——CLI 帮助中列出的 20 个Languages:子命令正是这 20 个AutoService模块的投影见 cli/pom.xml 对languages/各模块的依赖聚合。5.2 CLI子命令优先于-l选项README 的 CLI 说明 规定语言可以用-l language参数设置也可以作为子命令传入jplag [jplag options] -l language name [language options]且子命令优先于-l。源码中 CliInputHandler 直接以子命令名查询语言模块Language language LanguageLoader.getLanguage(subcommand.commandSpec().name()) .orElseThrow(() - new CliException(IMPOSSIBLE_EXCEPTION));子命令形式的主要好处是支持语言专属选项每个模块可通过getOptions()返回一个 LanguageOptions 子类其中的选项会自动展开为对应子命令的参数例如jplag java -h可查看 Java 子命令的全部选项。MultiLanguage 即是一个自带选项的示例它允许指定参与多语言解析的具体语言集合其minimumTokenMatch()取所选语言中的最小值。5.3 Multi-Language 模块的边界multi子命令由 MultiLanguage 实现是一个“多语言门面”fileExtensions()聚合 classpath 上所有其他语言模块的扩展名parse()将每个源文件按其扩展名委托给对应的具体语言模块MultiLanguageParser解析时会输出警告This module only allows parsing of multiple languages. No comparisons will be made between languages——即它只解决“混合语言提交集都能被解析”的问题相似度比较仍只在同语言 token 列表之间进行其supportsMultiLanguage()返回false防止被再次嵌套进 multi 门面。六、按场景选择语言模块的实践建议结合上述事实选型时可按以下规则判断C 与 C 混用优先使用cppmature、ANTLR 4、对 C 扩展名有优先级clegacy仅在需要旧版 C 行为时考虑其 README 也明确建议 C 代码使用 cpp 模块JavaScript/TypeScript 提交集两者共用 TypeScript 语法实现javascript模块只是扩展名与标识符不同的变体可任选其一处理各自文件多文件混合时使用multiEMF 场景.ecore元模型文件用emfbetaEMF 实例模型用emf-modelalphaAPI 集成且元模型动态变化时可研究emf-metamodel-dynamic子模块纯文本text模块基于 CoreNLP 的朴素分词标签为 legacy 且 README 标注“naive, use with caution”其结果解释需格外谨慎对结果稳健性要求高优先选择 mature 模块Java、C、C#、Python、Kotlin、R、Rust、Scalabeta/alpha 模块的结果建议作为参考并结合人工复核灵敏度调节在选定模块后用-t/--min-tokens在该模块minimumTokenMatch默认值附近调节并用--similarity-threshold过滤低相似度比较均见 README CLI 参数表。七、验证与扩展TokenPrinter、language-testutils 与新增模块流程理解各语言模块“实际产生了什么”最直观的工具是 TokenPrinter它逐行打印源代码并在每行下方标注该行产生的 token例如10 public class Example { |CLASS |CLASS{ 11 private int number; |FIELD各语言模块的单元测试普遍采用 language-testutils 提供的基础设施测试类继承LanguageModuleTest通过TestDataCollector声明测试源文件、覆盖率检查与addTokenPositionTests位置断言测试文件内用标记源码行、$行标注期望 token 的列号、类型与长度。以 languages 聚合 POM 为例language-testutils已作为test-jar依赖注入所有语言模块的测试作用域。若要新增语言模块docs/4.-Adding-New-Languages.md 给出了完整流程创建 Language 类与 TokenType 实现ANTLR 场景可复用language-antlr-utils中的AbstractAntlrLanguage/AbstractAntlrParser框架、在 languages/pom.xml 注册子模块、为 cli 与 coverage-report 模块添加依赖、更新 README 与docs文档。由于加载完全依赖 ServiceLoader只要新模块被加入 classpath 且带AutoService(Language.class)CLI 子命令与-l选项即可自动识别该语言。小结JPlag 的语言支持体系可以概括为三层其一languages/下 21 个 Maven 子模块按统一契约Language接口封装各语言的解析与 token 化并各自标注 mature/beta/alpha/legacy/unknown 成熟度标签其二LanguageLoader 通过 ServiceLoader 以 identifier 为键动态发现模块使 CLI 子命令、-l选项与 Java APIJPlagOptions直接持有Language实例三条使用路径共享同一套语言注册表其三multi门面与hasPriority()/supportsMultiLanguage()等机制处理了 C/C、JavaScript/TypeScript 等扩展名重叠与混合提交集的边界情形。选择检测方案时先按语言在上表中的 state 标签评估可信度再用模块默认值扩展名、minimumTokenMatch与-t等 CLI 参数校准灵敏度即可得到可复现的检测配置。赞分享代码质量教育后端【免费下载链接】JPlagState-of-the-Art Source Code Plagiarism Collusion Detection. Check for plagiarism in a set of programs.项目地址https://gitcode.com/gh_mirrors/jp/JPlag点击查看免费下载相关推荐A380X WASM 系统架构解析Rust 与 C 双语言机载系统模块全景A380X WASM 系统架构解析Rust 与 C 双语言机载系统模块全景 导读 本文以仓库中 fbw a380x/src/wasm/README.md游戏开发Tuist模块文档翻译多语言支持Tuist模块文档翻译多语言支持 在全球化软件开发中多语言支持是提升用户体验的关键环节。Tuist作为一款专注于简化Apple平台项目管理的工具通过系统化开发工具CLI后端云原生react-native-app-tour事件回调实战如何用3个DeviceEventEmitter事件追踪用户引导完成情况react native app tour事件回调实战如何用3个DeviceEventEmitter事件追踪用户引导完成情况 react native app创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑