Class VariationDiffParser
java.lang.Object
org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser
Parser that parses
VariationDiffs 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
Nested ClassesModifier and TypeClassDescriptionstatic final recordOne line of a diff. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final Stack<DiffNode<DiffLinesLabel>> A stack containing the current path after the edit from the root of the currently parsedVariationDiffto the currently parsedDiffNode.private final Stack<DiffNode<DiffLinesLabel>> A stack containing the current path before the edit from the root of the currently parsedVariationDiffto the currently parsedDiffNode.private DiffNode<DiffLinesLabel> (package private) final VariationDiffParseOptions -
Constructor Summary
ConstructorsModifierConstructorDescriptionprivateInitializes the parse state. -
Method Summary
Modifier and TypeMethodDescriptionprivate voidaddNode(DiffNode<DiffLinesLabel> newNode) Adds a fully parsed node into theVariationDiff.static VariationDiff<DiffLinesLabel> createVariationDiff(BufferedReader fullDiff, Source source, VariationDiffParseOptions options) Default parsing method forVariationDiffs from diffs.static VariationDiff<DiffLinesLabel> createVariationDiff(String fullDiff, Source source, VariationDiffParseOptions parseOptions) The same ascreateVariationDiff(BufferedReader, Source, VariationDiffParseOptions)but with the diff given as a single string with line breaks instead of aBufferedReader.static VariationDiff<DiffLinesLabel> createVariationTree(BufferedReader file, Source source, VariationDiffParseOptions options) Parses a variation tree from a source file.private VariationDiff<DiffLinesLabel> parse(Source source, org.apache.commons.lang3.function.FailableSupplier<VariationDiffParser.DiffLine, IOException> lines) Parses the line difffullDiff.static CommitDiffparseCommit(Repository repo, String commitHash) Parses the given commit of the given repository.private voidparseLine(LogicalLine line, DiffType diffType, DiffLineNumber lastLineNumber) Parses one logical line and most notably, handles conditional macros.static PatchDiffparsePatch(Repository repo, String file, String commitHash) Parses the given patch of the given repository.private voidpopIfChain(Time time, DiffLineNumber elseLineNumber, LogicalLine line) Pop the stack 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 parsedVariationDiffto the currently parsedDiffNode.The granularity of the
VariationDiffs 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 resultingVariationDiffand thereforebeforeStackwill never contain an artifact node. -
afterStack
A stack containing the current path after the edit from the root of the currently parsedVariationDiffto the currently parsedDiffNode.See
beforeStackfor 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 parsedDiffNodewas not an artifact,lastArtifactisnull.This state is used to implement
VariationDiffParseOptions.collapseMultipleCodeLines().
-
-
Constructor Details
-
VariationDiffParser
Initializes the parse state.- See Also:
-
-
Method Details
-
createVariationDiff
public static VariationDiff<DiffLinesLabel> createVariationDiff(String fullDiff, Source source, VariationDiffParseOptions parseOptions) throws DiffParseException The same ascreateVariationDiff(BufferedReader, Source, VariationDiffParseOptions)but with the diff given as a single string with line breaks instead of aBufferedReader.- Throws:
DiffParseException- iffullDiffcouldn't be parsed
-
createVariationDiff
public static VariationDiff<DiffLinesLabel> createVariationDiff(BufferedReader fullDiff, Source source, VariationDiffParseOptions options) throws IOException, DiffParseException Default parsing method forVariationDiffs 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.source- theSourceoffullDiffoptions-VariationDiffParseOptionsfor the parsing process.- Returns:
- A parsed
VariationDiffupon success or an error indicating why parsing failed. - Throws:
IOException- when reading fromfullDifffails.DiffParseException- if an error in the diff or macro syntax is detected
-
createVariationTree
public static VariationDiff<DiffLinesLabel> createVariationTree(BufferedReader file, Source source, VariationDiffParseOptions options) throws IOException, DiffParseException Parses a variation tree from a source file. This method is similar tocreateVariationDiff(BufferedReader, Source, VariationDiffParseOptions)but acts as if all lines where unmodified.- Parameters:
file- The source code file (not a diff) to be parsed.source- theSourceoffileoptions-VariationDiffParseOptionsfor the parsing process.- Returns:
- A parsed
VariationDiff. - Throws:
IOException- ifffilethrows anIOExceptionDiffParseException- if an error in the diff or macro syntax is detected
-
parse
private VariationDiff<DiffLinesLabel> parse(Source source, org.apache.commons.lang3.function.FailableSupplier<VariationDiffParser.DiffLine, IOException> lines) throws IOException, DiffParseExceptionParses the line difffullDiff.- Parameters:
source- theSourceoflineslines- should supply successive lines of the diff to be parsed, ornullif there are no more lines to be parsed.- Returns:
- the parsed
VariationDiff - Throws:
IOException- ifflines.get()throwsIOExceptionDiffParseException- 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() == truediffType- whetherlinewas added, inserted or unchangedlastLineNumber- the last physical line ofline- Throws:
DiffParseException- if erroneous preprocessor macros are detected
-
popIfChain
private void popIfChain(Time time, DiffLineNumber elseLineNumber, LogicalLine line) throws DiffParseException Pop the stack 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 numbersare adjusted- Parameters:
time- which stack to pop the if chain (i.e.,beforeStackorafterStack)elseLineNumber- the first line of the else which causes this IF to be poppedline- the line containing the endif- Throws:
DiffParseException- ifstackdoesn'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- iflineerroneous 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.
-