{"id":36413522,"url":"https://github.com/atextor/syntax-annotation","last_synced_at":"2026-01-31T20:10:23.653Z","repository":{"id":52852978,"uuid":"519961163","full_name":"atextor/syntax-annotation","owner":"atextor","description":"Java compile time syntax check for strings containing other languages","archived":false,"fork":false,"pushed_at":"2023-11-09T04:05:47.000Z","size":435,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T18:29:13.366Z","etag":null,"topics":["compile-time-annotation","compile-time-checking","java","syntax-analysis","type-safe","type-safety"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atextor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-08-01T04:19:29.000Z","updated_at":"2025-10-09T10:59:10.000Z","dependencies_parsed_at":"2022-08-13T02:10:22.413Z","dependency_job_id":null,"html_url":"https://github.com/atextor/syntax-annotation","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/atextor/syntax-annotation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atextor%2Fsyntax-annotation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atextor%2Fsyntax-annotation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atextor%2Fsyntax-annotation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atextor%2Fsyntax-annotation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atextor","download_url":"https://codeload.github.com/atextor/syntax-annotation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atextor%2Fsyntax-annotation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28952637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T18:30:42.805Z","status":"ssl_error","status_checked_at":"2026-01-31T18:30:19.593Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compile-time-annotation","compile-time-checking","java","syntax-analysis","type-safe","type-safety"],"created_at":"2026-01-11T16:55:26.152Z","updated_at":"2026-01-31T20:10:23.648Z","avatar_url":"https://github.com/atextor.png","language":"Java","readme":"# syntax-annotation\n\n[![build](https://github.com/atextor/syntax-annotation/actions/workflows/build.yml/badge.svg)](https://github.com/atextor/syntax-annotation/actions/workflows/build.yml) ![Maven Central Version](https://img.shields.io/maven-central/v/de.atextor/syntax-annotation) [![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\n_Make your Java code a little more type safe by adding compile time syntax\nchecks for strings containing other languages!_\n\nAdd the `@Syntax` annotation to your string literals and have your compilation/build fail if there\nare syntax errors inside the string. This works on local variables and on fields, including static\nfields. It works on regular strings (including strings that are split into parts and concatenated\nusing the + operator) as well as text blocks.\n\nIf you have some language embedded in a string, this would normally only fail at runtime:\n![Java code with a string containing a JSON document with a syntax erro](docs/demo1.png)\n\nAdd `@Syntax` to the string:\n![The same Java code, but with the @Syntax(JSON.class) annotation before the string](docs/demo2.png)\n\nHave the problem reported during compilation directly in your IDE - no IDE plugin required:\n![IDE build output showing the compiler error raised by the JSON syntax error](docs/demo3.png)\n\n`@Syntax` not only works in the IDE, but also in your regular build:\n![Maven build output showing the compiler error raised by the JSON syntax error](docs/demo4.png)\n\n## Usage\n\n**syntax-annotation** requires Java 25.\n\nAdd the following dependency to your Maven `pom.xml`:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ede.atextor\u003c/groupId\u003e\n  \u003cartifactId\u003esyntax-annotation\u003c/artifactId\u003e\n  \u003cversion\u003e1.1.0\u003c/version\u003e\n  \u003cscope\u003ecompile\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nNote the `compile` scope - since only an additional compile-time check is done, no runtime\ndependencies are added to your project.\n\nSince the annotation processor accesses the Java compiler, its module needs access to the\ncorresponding module. Add the following configuration to your `pom.xml`:\n\n```xml\n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n            \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e3.8.1\u003c/version\u003e\n            \u003cconfiguration\u003e\n                \u003cshowWarnings\u003etrue\u003c/showWarnings\u003e\n            \u003c/configuration\u003e\n            \u003cexecutions\u003e\n                \u003cexecution\u003e\n                    \u003cid\u003edefault-compile\u003c/id\u003e\n                    \u003cphase\u003ecompile\u003c/phase\u003e\n                    \u003cgoals\u003e\n                        \u003cgoal\u003ecompile\u003c/goal\u003e\n                    \u003c/goals\u003e\n                    \u003cconfiguration\u003e\n                        \u003cfork\u003etrue\u003c/fork\u003e\n                        \u003ccompilerArgs\u003e\n                            \u003carg\u003e-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED\u003c/arg\u003e\n                        \u003c/compilerArgs\u003e\n                    \u003c/configuration\u003e\n                \u003c/execution\u003e\n            \u003c/executions\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n## Supported languages\n\nCurrently, **syntax-annotation** provides check functions for the following languages:\n\n* *JSON*: Use `de.atextor.syntax.JSON.class` as argument for `@Syntax`. In order to use this, make sure you have\n  `com.fasterxml.jackson.core:jackson-core:2.21.0` and\n  `com.fasterxml.jackson.core:jackson-databind:2.21.0` in your compile build path, i.e., add the\n  corresponding dependency with scope compile if necessary.\n* *Regular Expressions (as recognized by [java.util.regex.Pattern#compile](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html#compile(java.lang.String)))*: Use `de.atextor.syntax.RegExp.class` as argument for `@Syntax`. No additional\n  dependencies are required.\n* *XML*: Use `de.atextor.syntax.XML.class` as argument for `@Syntax`. No additional\n  dependencies are required.\n* *[RDF/Turtle](https://www.w3.org/TR/turtle/)*: Use `de.atextor.syntax.Turtle.class` as argument for `@Syntax`. In order to use this, make\n  sure you have `org.apache.jena:jena-arq:5.6.0` in your compile build path, i.e., add the\n  corresponding dependency with scope compile if necessary.\n\n## Custom languages\n\nSupport for additional languages can easily be added. Write a class that implements\n`java.util.Function\u003cString, Optional\u003cString\u003e\u003e`: The function that takes the string to syntax check\nas input and returns `Optional.empty()` if the syntax is valid, or `Optional.of(\"error message\")` if\nthe syntax is invalid. The class needs to have a default constructor and needs to be available on\nthe compile time class path. Then you can pass it as argument to the `@Syntax` annotation.\n\nFor example:\n```java\n/**\n * Syntax check: the annotated string must be equal to \"foo\"\n */\npublic class FooCheck implements Function\u003cString, Optional\u003cString\u003e\u003e {\n    @Override\n    public Optional\u003cString\u003e apply(String s) {\n        return s.equals(\"foo\") ? Optional.empty() : Optional.of(s + \" IS NOT FOO\");\n    }\n}\n```\n\nThen, to use it:\n```java\npublic void fooDemo() {\n    @Syntax(FooCheck.class) String thisMustBeFoo = \"something else\";\n}\n```\n\nThis will lead to a compilation failure:\n![IDE build output showing the compiler error raised by FooCheck](docs/demo5.png)\n\nNote that class path setup might be tricky if the syntax check function is part of the same code\nbase that wants to use it at compile time. To reliably set this up, put the check function into its\nown maven module and add this module as dependency with compile scope to the code that uses the\nfunction as `@Syntax` argument.\n\nIf your check function implementation uses a third party dependency, this dependency must be present\n(at least in compile scope) in the code that uses `@Syntax`. For example, the `JSON` check function\nthat is part of syntax-annotation, uses Jackson to do its parsing, which is why you need to have\nJackson in your dependencies to use this check function.\n\n## Release notes\n\n* 1.0.0 First release\n\n## Contact\n\n**syntax-annotation** is developed by Andreas Textor \u003c\u003cmail@atextor.de\u003e\u003e.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatextor%2Fsyntax-annotation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatextor%2Fsyntax-annotation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatextor%2Fsyntax-annotation/lists"}