5.19 source-tree with from: jar — the source a jar was compiled from
The source-tree kind (§5.21) with from: jar reads a jar’s source; the source kind that did before
is retired: a producer file that still writes kind: source does not load, and the realm reports it as a
problem naming the file.
Change kind: source to kind: source-tree, from: jar and emit: callsites to emit: calls: keys,
ids and columns are as they were.
A from: jar producer reads source files where they are, when a query reaches them, keyed by what a
jar row (§5.18) already carries. Nothing is ingested; the rows are transient like any fetch.
- { name: javaSourceFile, kind: source-tree, from: jar, emit: files, roots: [src] } # key: a sourceKey- { name: javaSourceSpan, kind: source-tree, from: jar, emit: spans, roots: [src], context: 6 } # key: a spanKey- { name: javaDeclaration, kind: source-tree, from: jar, emit: declarations, roots: [src] } # sourceKey or spanKey- { name: javaCallSites, kind: source-tree, from: jar, emit: calls, roots: [src] } # key: a spanKey- { name: javaLocals, kind: source-tree, from: jar, emit: locals, roots: [src] } # sourceKey or spanKey- { name: upstream, kind: source-tree, from: jar, emit: spans, roots: [ { git: "https://github.com/acme/acme", ref: "v{version}" } ] }MATCH (j:Jar {path: 'data/jars/app.jar'})-[:HAS_CALL]->(c:JavaMethodCall {calleeOwner: 'java.util.Map', calleeName: 'put'}) -[:AT_SITE]->(cs:JavaCallSite)RETURN c.caller, cs.receiver, cs.arguments, cs.argumentTypesThe contract:
- Five emits.
filesreturns the file asourceKeynames:root,path,language,lines,sha256,package,candidates, and for a git rootcommitandurl.spansreturns the numbered lines withincontext(default 6, at most 50) of aspanKey’s line, withmatches— whether the word the key expects appears on them — andinRange.declarationsreturns, for asourceKey, every type, field, constructor, method and initializer the file declares, or for aspanKeythe innermost one around the line:kind,name, binaryowner,fromLine/toLine,signature,modifiers,annotations(names),annotationText(each in full, as written),javadoc, and for a member its numberedtext.callsreturns the calls on aspanKey’s line whose method (or, for a constructor, class) is the key’s word:receiver,receiverType,arguments,argumentTypes,argumentTypesResolved,enclosing, andresolution:typewhen the receiver’s static type is known, elsename(§5.21).localsreturns, for asourceKey, every local variable the file declares, or for aspanKeythose of the method, constructor or initializer around the line:kind(local,for,foreach,resource,pattern),name,line,declaredTypeas written,isVar,isFinal,initializer,initializerType,varEligibleandvarPreservesType(below),enclosing,enclosingKind,enclosingOwner, and the numberedtextof the declaration. Every row carriesid,sourceKey,jarPathandanchorKey, so a span or declaration joins back to its file bysourceKey. - Where source is looked for, in order. A
<jar name>-sources.jarbeside the jar — for a war,<war name>-sources.jarbeside the war; for a folder of classes, the project it was built in, read as a source tree (the folder abovetargetorbuild:shop/target/classesfindsshop/src/main/java/com/x/Cache.java; a project folder named as the key is itself the tree); then each root, in the order declared — a-sources.jarnamed as a root, a<jar name>-sources.jarinside a root folder, the folder itself as a source tree, or a git repository. Paths resolve as a jar path does: the world’sdata/tree, an operator-trusted root, the declaring realm’s own directory. In a tree a source path is found under any module and source folder (core/src/main/java/com/x/Cache.javaforcom/x/Cache.java); when more than one file matches, the first in path order is read andcandidatessays how many there were. The first root holding the path answers. - A git root is read at a commit.
refis a commit, tag or branch;{version}in it is replaced by the jar’s version. A tag or branch is resolved to its commit first, and rows report the commit, so the same rows come back whatever the tag later points at. Only https URLs are accepted, held to the same address rule as any fetched URL; a repository needing credentials is refused, not waited on. The first read of a commit lists its files; a file’s content is fetched the first time it is read. - Declarations, call sites and locals need a syntax tree. They answer for Java source; a file in
another language answers
filesandspans, and these emits return nothing for it with aPRODUCER_ERRORwarning saying so. A file with syntax errors answers around them. An argument’s type is resolved from the file alone —new X(…), a literal, a cast, a parameter, a local declared before the call, a field of an enclosing type — through the file’s own types, single-type imports,java.langand the file’s package. A type only another file could explain is returned as written withargumentTypesResolvedfalse; a method’s return value is unknown. - Whether
varwould do.varEligibleis the language’s rule: one variable, given a value that is notnull, an array initializer, a lambda or a method reference (every enhanced-forvariable; never a pattern binding).varPreservesTypesays whethervarwould give the variable the type it declares: true forString s = "x"orKey k = new Key(id); false when the initializer’s type is another one (long n = 1,List<X> xs = new ArrayList<>()), an anonymous class, or a diamond under a parameterised type; null when the initializer’s type is not in the file — never guessed. It is null for a local already declared withvarand for onevarcannot replace. - What is honest about absence. A key whose path no root holds returns nothing — a generated class
has no source. A jar for which no root at all could be found, a declared root that could not be
read, a git ref that names nothing, and a file larger than
maxFileKb(default 1024) are each aPRODUCER_ERRORwarning naming what was missing. A source that is not the jar’s version shows asmatches: falseon its spans and declarations; its line numbers cannot be trusted.
Cost: a root is listed once and kept for later keys and queries (an archive until it changes on disk, a commit for good); a folder tree is listed again when a lookup misses, at most once per fetch. Each key is then one file read, and a syntax-tree emit parses a file once per fetch however many keys name it. A git root’s first query pays for a shallow, blob-less fetch of the commit; each file read from it for the first time is one more fetch.

