Class VariationDiffParser
java.lang.Object
org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser
Parser that parses
VariationDiff
s from text-based diffs.
Note: Weird line continuations and comments can cause misidentification of conditional macros.
The following examples are all correct according to the C11 standard: (comment end is marked by
*\/
):
/*
#ifdef A
*\/
#ifdef /*
*\/ A
#endif
# /**\/ ifdef
#endif
# \
ifdef
#endif
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic final record
One line of a diff. -
Field Summary
Modifier and TypeFieldDescriptionprivate final Stack<DiffNode<DiffLinesLabel>>
A stack containing the current path after the edit from the root of the currently parsedVariationDiff
to the currently parsedDiffNode
.private final Stack<DiffNode<DiffLinesLabel>>
A stack containing the current path before the edit from the root of the currently parsedVariationDiff
to the currently parsedDiffNode
.private DiffNode<DiffLinesLabel>
(package private) final VariationDiffParseOptions
-
Constructor Summary
ModifierConstructorDescriptionprivate
Initializes the parse state. -
Method Summary
Modifier and TypeMethodDescriptionprivate void
addNode
(DiffNode<DiffLinesLabel> newNode) Adds a fully parsed node into theVariationDiff
.static VariationDiff<DiffLinesLabel>
createVariationDiff
(BufferedReader fullDiff, VariationDiffParseOptions options) Default parsing method forVariationDiff
s from diffs.static VariationDiff<DiffLinesLabel>
createVariationDiff
(String fullDiff, VariationDiffParseOptions parseOptions) The same ascreateVariationDiff(BufferedReader, VariationDiffParseOptions)
but with the diff given as a single string with line breaks instead of aBufferedReader
.static VariationDiff<DiffLinesLabel>
createVariationTree
(BufferedReader file, VariationDiffParseOptions options) Parses a variation tree from a source file.private VariationDiff<DiffLinesLabel>
parse
(org.apache.commons.lang3.function.FailableSupplier<VariationDiffParser.DiffLine, IOException> lines) Parses the line difffullDiff
.static CommitDiff
parseCommit
(Repository repo, String commitHash) Parses the given commit of the given repository.private void
parseLine
(LogicalLine line, DiffType diffType, DiffLineNumber lastLineNumber) Parses one logical line and most notably, handles conditional macros.static PatchDiff
parsePatch
(Repository repo, String file, String commitHash) Parses the given patch of the given repository.private void
popIfChain
(Stack<DiffNode<DiffLinesLabel>> stack, DiffLineNumber elseLineNumber) Popstack
until an IF node is popped.
-
Field Details
-
options
-
beforeStack
A stack containing the current path before the edit from the root of the currently parsedVariationDiff
to the currently parsedDiffNode
.The granularity of the
VariationDiff
s parsed by this class is always lines because line diffs can't represent different granularities. This implies that there are no nested artifact nodes in the resultingVariationDiff
and thereforebeforeStack
will never contain an artifact node. -
afterStack
A stack containing the current path after the edit from the root of the currently parsedVariationDiff
to the currently parsedDiffNode
.See
beforeStack
for more explanations. -
lastArtifact
The last artifact node which was parsed byparseLine(org.variantsync.diffdetective.variation.diff.parse.LogicalLine, org.variantsync.diffdetective.variation.diff.DiffType, org.variantsync.diffdetective.diff.text.DiffLineNumber)
. If the last parsedDiffNode
was not an artifact,lastArtifact
isnull
.This state is used to implement
VariationDiffParseOptions.collapseMultipleCodeLines()
.
-
-
Constructor Details
-
VariationDiffParser
Initializes the parse state.
-
-
Method Details
-
createVariationDiff
public static VariationDiff<DiffLinesLabel> createVariationDiff(String fullDiff, VariationDiffParseOptions parseOptions) throws DiffParseException The same ascreateVariationDiff(BufferedReader, VariationDiffParseOptions)
but with the diff given as a single string with line breaks instead of aBufferedReader
.- Throws:
DiffParseException
- iffullDiff
couldn't be parsed
-
createVariationDiff
public static VariationDiff<DiffLinesLabel> createVariationDiff(BufferedReader fullDiff, VariationDiffParseOptions options) throws IOException, DiffParseException Default parsing method forVariationDiff
s from diffs. This implementation has options to collapse multiple code lines into one node and to discard empty lines. This parsing algorithm is described in detail in Sören Viegener's bachelor's thesis.- Parameters:
fullDiff
- The full diff of a patch obtained from a buffered reader.options
-VariationDiffParseOptions
for the parsing process.- Returns:
- A parsed
VariationDiff
upon success or an error indicating why parsing failed. - Throws:
IOException
- when reading fromfullDiff
fails.DiffParseException
- if an error in the diff or macro syntax is detected
-
createVariationTree
public static VariationDiff<DiffLinesLabel> createVariationTree(BufferedReader file, VariationDiffParseOptions options) throws IOException, DiffParseException Parses a variation tree from a source file. This method is similar tocreateVariationDiff(BufferedReader, VariationDiffParseOptions)
but acts as if all lines where unmodified.- Parameters:
file
- The source code file (not a diff) to be parsed.options
-VariationDiffParseOptions
for the parsing process.- Returns:
- A parsed
VariationDiff
. - Throws:
IOException
- ifffile
throws anIOException
DiffParseException
- if an error in the diff or macro syntax is detected
-
parse
private VariationDiff<DiffLinesLabel> parse(org.apache.commons.lang3.function.FailableSupplier<VariationDiffParser.DiffLine, IOException> lines) throws IOException, DiffParseExceptionParses the line difffullDiff
.- Parameters:
lines
- should supply successive lines of the diff to be parsed, ornull
if there are no more lines to be parsed.- Returns:
- the parsed
VariationDiff
- Throws:
IOException
- ifflines.get()
throwsIOException
DiffParseException
- if an error in the line diff or the underlying preprocessor syntax is detected
-
parseLine
private void parseLine(LogicalLine line, DiffType diffType, DiffLineNumber lastLineNumber) throws DiffParseException Parses one logical line and most notably, handles conditional macros.- Parameters:
line
- a logical line withline.isComplete() == true
diffType
- whetherline
was added, inserted or unchangedlastLineNumber
- the last physical line ofline
- Throws:
DiffParseException
- if erroneous preprocessor macros are detected
-
popIfChain
private void popIfChain(Stack<DiffNode<DiffLinesLabel>> stack, DiffLineNumber elseLineNumber) throws DiffParseException Popstack
until an IF node is popped. If there were ELSEs or ELIFs between an IF and an ENDIF, they were placed on the stack and have to be popped now. Theend line numbers
are adjusted- Parameters:
stack
- the stack which should be poppedelseLineNumber
- the first line of the else which causes this IF to be popped- Throws:
DiffParseException
- ifstack
doesn't contain an IF node
-
addNode
Adds a fully parsed node into theVariationDiff
. Annotations also pushed to the relevant stacks.- Parameters:
newNode
- the fully parsed node to be added- Throws:
DiffParseException
- ifline
erroneous preprocessor macros are detected
-
parseCommit
Parses the given commit of the given repository.- Parameters:
repo
- The repository from which a commit should be parsed.commitHash
- Hash of the commit to parse.- Returns:
- A CommitDiff describing edits to variability introduced by the given commit relative to its first parent commit.
- Throws:
IOException
- when an error occurred.
-
parsePatch
public static PatchDiff parsePatch(Repository repo, String file, String commitHash) throws IOException Parses the given patch of the given repository.- Parameters:
repo
- The repository from which a patch should be parsed.file
- The file that was edited by the patch.commitHash
- The hash of the commit in which the patch was made.- Returns:
- A PatchDiff describing edits to variability introduced by the given patch relative to the corresponding commit's first parent commit.
- Throws:
IOException
- when an error occurred.AssertionError
- when no such patch exists.
-