Skip to content

Commit

Permalink
feat: add enhancing of import declarations node to fix import issue
Browse files Browse the repository at this point in the history
  • Loading branch information
jpedroh committed May 2, 2024
1 parent d5b3c87 commit ad2fe09
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
package de . fosd . jdime . common ; import de . fosd . jdime . common . operations . AddOperation ; import AST . * ; import de . fosd . jdime . common . operations . ConflictOperation ; public class ASTNodeArtifact extends Artifact < ASTNodeArtifact > { private ASTNodeArtifact ( final ASTNode < ? > astnode ) { assert ( astnode != null ) ; this . astnode = astnode ; this . initializeChildren ( ) ; } public ASTNodeArtifact ( final FileArtifact artifact ) { assert ( artifact != null ) ; setRevision ( artifact . getRevision ( ) ) ; ASTNode < ? > astnode ; if ( artifact . isEmpty ( ) ) { astnode = new ASTNode < > ( ) ; } else { Program p = initProgram ( ) ; p . addSourceFile ( artifact . getPath ( ) ) ; astnode = p ; } this . astnode = astnode ; this . initializeChildren ( ) ; renumberTree ( ) ; } }
package de . fosd . jdime . common ; import AST . * ; import de . fosd . jdime . common . operations . ConflictOperation ; import de . fosd . jdime . common . operations . AddOperation ; public class ASTNodeArtifact extends Artifact < ASTNodeArtifact > { private ASTNodeArtifact ( final ASTNode < ? > astnode ) { assert ( astnode != null ) ; this . astnode = astnode ; this . initializeChildren ( ) ; } public ASTNodeArtifact ( final FileArtifact artifact ) { assert ( artifact != null ) ; setRevision ( artifact . getRevision ( ) ) ; ASTNode < ? > astnode ; if ( artifact . isEmpty ( ) ) { astnode = new ASTNode < > ( ) ; } else { Program p = initProgram ( ) ; p . addSourceFile ( artifact . getPath ( ) ) ; astnode = p ; } this . astnode = astnode ; this . initializeChildren ( ) ; renumberTree ( ) ; } }
14 changes: 14 additions & 0 deletions bin/tests/scenarios/import_declarations_grouping_node/base.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package br.fosd.jdime.stats;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.TreeSet;

import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import de.fosd.jdime.common.LangElem;

public class ASTStats {
}
13 changes: 13 additions & 0 deletions bin/tests/scenarios/import_declarations_grouping_node/left.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package br.fosd.jdime.stats;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.TreeSet;

import de.fosd.jdime.common.LangElem;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

public class ASTStats {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package br . fosd . jdime . stats ; import java . text . DecimalFormat ; import java . util . HashMap ; import java . util . TreeSet ; import de . fosd . jdime . common . LangElem ; import java . util . logging . Level ; import java . util . logging . Logger ; public class ASTStats { }
12 changes: 12 additions & 0 deletions bin/tests/scenarios/import_declarations_grouping_node/right.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package br.fosd.jdime.stats;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import de.fosd.jdime.common.LangElem;

public class ASTStats {
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
package de . fosd . jdime . merge ; import java . util . List ; import AST . * ; import de . fosd . jdime . operations . AddOperation ; import de . fosd . jdime . operations . ConflictOperation ; import de . fosd . jdime . operations . MergeOperation ; import static de . fosd . jdime . artifact . Artifacts . root ; import static de . fosd . jdime . strdump . DumpMode . PLAINTEXT_TREE ;
package de . fosd . jdime . merge ; import java . util . List ; import AST . * ; import de . fosd . jdime . operations . AddOperation ; import de . fosd . jdime . operations . ConflictOperation ; import de . fosd . jdime . operations . MergeOperation ; import static de . fosd . jdime . artifact . Artifacts . root ; import static de . fosd . jdime . strdump . DumpMode . PLAINTEXT_TREE ;
2 changes: 1 addition & 1 deletion bin/tests/scenarios/jdime_matching_issue/merge.java
Original file line number Diff line number Diff line change
@@ -1 +1 @@
package de . fosd . jdime . artifact ; import java . security . MessageDigest ; public abstract class Artifact < T extends Artifact < T > > implements Comparable < T > , StatisticsInterface { public boolean hasChanges ( Revision revision ) { if ( this . revision . equals ( revision ) ) { return false ; } if ( ! hasMatching ( revision ) ) { return true ; } T match = getMatching ( revision ) . getMatchingArtifact ( this ) ; return getTreeSize ( ) != match . getTreeSize ( ) || ! getTreeHash ( ) . equals ( match . getTreeHash ( ) ) ; } }
package de . fosd . jdime . artifact ; import java . security . MessageDigest ; public abstract class Artifact < T extends Artifact < T > > implements Comparable < T > , StatisticsInterface { public boolean hasChanges ( Revision revision ) { if ( this . revision . equals ( revision ) ) { return false ; } if ( ! hasMatching ( revision ) ) { return true ; } T match = getMatching ( revision ) . getMatchingArtifact ( this ) ; return getTreeSize ( ) != match . getTreeSize ( ) || ! getTreeHash ( ) . equals ( match . getTreeHash ( ) ) ; } }
Original file line number Diff line number Diff line change
@@ -1 +1 @@
package de . fosd . jdime ; import java . io . File ; import java . net . URISyntaxException ; import java . net . URL ; import java . util . Arrays ; import org . junit . BeforeClass ; import static org . junit . Assert . assertNotNull ; import static org . junit . Assert . assertTrue ; import static org . junit . Assert . fail ; public class JDimeTest { protected static File file ( File parent , String child ) { File f = new File ( parent , child ) ; assertTrue ( f + " does not exist." , f . exists ( ) ) ; return f ; } protected static File file ( File parent , String name , String ... names ) { if ( names != null ) { String path = String . format ( "%s/%s" , name , String . join ( "/" , names ) ) ; return file ( parent , path ) ; } else { return file ( parent , name ) ; } } protected static File file ( String path ) { URL res = JDimeTest . class . getResource ( path ) ; assertNotNull ( "The file " + path + " was not found." , res ) ; try { return new File ( res . toURI ( ) ) ; } catch ( URISyntaxException e ) { fail ( e . getMessage ( ) ) ; return null ; } } protected static File file ( String name , String ... names ) { if ( names != null ) { String path = String . format ( "/%s/%s" , name , String . join ( "/" , names ) ) ; return file ( path ) ; } else { return file ( "/" + name ) ; } } }
package de . fosd . jdime ; import java . io . File ; import java . net . URISyntaxException ; import java . net . URL ; import java . util . Arrays ; import org . junit . BeforeClass ; import static org . junit . Assert . assertNotNull ; import static org . junit . Assert . assertTrue ; import static org . junit . Assert . fail ; public class JDimeTest { protected static File file ( File parent , String child ) { File f = new File ( parent , child ) ; assertTrue ( f + " does not exist." , f . exists ( ) ) ; return f ; } protected static File file ( File parent , String name , String ... names ) { if ( names != null ) { String path = String . format ( "%s/%s" , name , String . join ( "/" , names ) ) ; return file ( parent , path ) ; } else { return file ( parent , name ) ; } } protected static File file ( String path ) { URL res = JDimeTest . class . getResource ( path ) ; assertNotNull ( "The file " + path + " was not found." , res ) ; try { return new File ( res . toURI ( ) ) ; } catch ( URISyntaxException e ) { fail ( e . getMessage ( ) ) ; return null ; } } protected static File file ( String name , String ... names ) { if ( names != null ) { String path = String . format ( "/%s/%s" , name , String . join ( "/" , names ) ) ; return file ( path ) ; } else { return file ( "/" + name ) ; } } }
14 changes: 14 additions & 0 deletions model/src/cst_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ impl CSTNode<'_> {
CSTNode::NonTerminal(node) => node.contents(),
}
}

pub fn start_position(&self) -> Point {
match self {
CSTNode::Terminal(node) => node.start_position,
CSTNode::NonTerminal(node) => node.start_position,
}
}

pub fn end_position(&self) -> Point {
match self {
CSTNode::Terminal(node) => node.end_position,
CSTNode::NonTerminal(node) => node.end_position,
}
}
}

#[derive(Debug, Default, Clone)]
Expand Down
77 changes: 72 additions & 5 deletions parsing/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,73 @@ fn explore_node<'a>(node: Node, src: &'a str, config: &'a ParserConfiguration) -
}
}

fn tweak_import_declarations(root: CSTNode<'_>) -> CSTNode<'_> {
match root.kind() {
"program" => match root {
CSTNode::Terminal(_) => root.to_owned(),
CSTNode::NonTerminal(program) => {
let import_declaration_children: Vec<CSTNode> = program
.children
.iter()
.filter(|node| node.kind() == "import_declaration")
.cloned()
.collect();

if import_declaration_children.is_empty() {
return CSTNode::NonTerminal(program);
}

let import_declarations_start = import_declaration_children
.first()
.unwrap()
.start_position();

let import_declarations_end =
import_declaration_children.last().unwrap().end_position();

let import_declarations = CSTNode::NonTerminal(NonTerminal {
id: uuid::Uuid::new_v4(),
kind: "import_declarations",
children: import_declaration_children,
start_position: import_declarations_start,
end_position: import_declarations_end,
are_children_unordered: true,
});

let first_import_declaration_index = program
.children
.iter()
.position(|node| node.kind() == "import_declaration")
.unwrap();
let last_import_declaration_index = program
.children
.iter()
.rposition(|node| node.kind() == "import_declaration")
.unwrap();

let mut new_program_children: Vec<CSTNode<'_>> = vec![];
new_program_children.extend_from_slice(
&program.children.iter().as_slice()[..first_import_declaration_index],
);
new_program_children.push(import_declarations);
new_program_children.extend_from_slice(
&program.children.iter().as_slice()[last_import_declaration_index + 1..],
);

CSTNode::NonTerminal(NonTerminal {
id: program.id,
kind: program.kind,
start_position: program.start_position,
end_position: program.end_position,
children: new_program_children,
are_children_unordered: false,
})
}
},
_ => root.to_owned(),
}
}

pub fn parse_string<'a>(
src: &'a str,
config: &'a ParserConfiguration,
Expand All @@ -52,9 +119,9 @@ pub fn parse_string<'a>(
.set_language(config.language)
.map_err(|_| "There was an error while setting the parser language")?;

let parsed = parser.parse(src, None);
match parsed {
Some(parsed) => Result::Ok(explore_node(parsed.root_node(), src, config)),
None => Result::Err("It was not possible to parse the tree."),
}
let parsed = parser
.parse(src, None)
.ok_or("It was not possible to parse the tree.")?;
let root = explore_node(parsed.root_node(), src, config);
Ok(tweak_import_declarations(root))
}

0 comments on commit ad2fe09

Please sign in to comment.