@@ -572,3 +572,252 @@ class Example {
572572 for line in lines :
573573 # print(line)
574574 fp .write (line )
575+
576+
577+ def copy_and_rename_method (filename : str , signature : str , before : str , after : str ):
578+ """Helper to make a copy an entire method and rename it.
579+
580+ Goes line-by-line to detect the start of the block. Determines
581+ the end of the block by a closing brace at the same indentation
582+ level. This requires the file to be correctly formatted.
583+ The method is copied over and renamed in the method signature.
584+ The calls to both methods are separate and unaffected.
585+
586+ Example: consider the following class:
587+
588+ class Example {
589+ public void main(String[] args) {
590+ System.out.println("Hello World");
591+ }
592+
593+ public String foo() {
594+ return "bar";
595+ }
596+ }
597+
598+ To copy and rename the `main` method above, use:
599+
600+ copy_and_rename_method('path/to/file', 'public void main(String[] args)',
601+ 'main', 'foo1')
602+
603+ Args:
604+ filename (str): Path to source file
605+ signature (str): Full signature of the method to remove. Example:
606+ `public void main(String[] args)`.
607+ before (str): name of the method to be copied
608+ after (str): new name of the copied method
609+ """
610+ lines = []
611+ method = []
612+ leading_regex = None
613+ with open (filename , "r" ) as fp :
614+ line = fp .readline ()
615+ while line :
616+ # for each line, try to find the matching
617+ regex = re .compile ("(\\ s*)" + re .escape (signature ) + ".*" )
618+ match = regex .match (line )
619+ if match :
620+ leading_regex = re .compile (match .group (1 ) + "}" )
621+ lines .append (line )
622+ method .append (line .replace (before , after ))
623+ line = fp .readline ()
624+ continue
625+
626+ lines .append (line )
627+ # not in a ignore block - preserve the line
628+ if leading_regex :
629+ method .append (line )
630+ else :
631+ line = fp .readline ()
632+ continue
633+
634+ # detect the closing tag based on the leading spaces
635+ match = leading_regex .match (line )
636+ if match :
637+ # block is closed, resume capturing content
638+ leading_regex = None
639+ lines .append ("\n " )
640+ lines .extend (method )
641+
642+ line = fp .readline ()
643+
644+ with open (filename , "w" ) as fp :
645+ for line in lines :
646+ # print(line)
647+ fp .write (line )
648+
649+
650+ def add_javadoc (filename : str , signature : str , javadoc_type : str , content : List [str ]):
651+ """Helper to add a javadoc annoatation to a method.
652+
653+ Goes line-by-line to detect the start of the block.
654+ Then finds the existing method comment (if it exists). If the
655+ comment already exists, it will append the javadoc annotation
656+ to the javadoc block. Otherwise, it will create a new javadoc
657+ comment block.
658+
659+ Example: consider the following class:
660+
661+ class Example {
662+ public void main(String[] args) {
663+ System.out.println("Hello World");
664+ }
665+
666+ public String foo() {
667+ return "bar";
668+ }
669+ }
670+
671+ To add a javadoc annotation the `main` method above, use:
672+
673+ add_javadoc('path/to/file', 'public void main(String[] args)',
674+ 'deprecated', 'Please use foo instead.')
675+
676+ Args:
677+ filename (str): Path to source file
678+ signature (str): Full signature of the method to remove. Example:
679+ `public void main(String[] args)`.
680+ javadoc_type (str): The type of javadoc annotation. Example: `deprecated`.
681+ content (List[str]): The javadoc lines
682+ """
683+ lines : List [str ] = []
684+ annotations : List [str ] = []
685+ with open (filename , "r" ) as fp :
686+ line = fp .readline ()
687+ while line :
688+ # for each line, try to find the matching
689+ regex = re .compile ("(\\ s*)" + re .escape (signature ) + ".*" )
690+ match = regex .match (line )
691+ if match :
692+ leading_spaces = len (line ) - len (line .lstrip ())
693+ indent = leading_spaces * " "
694+ last_line = lines .pop ()
695+ while last_line .lstrip () and last_line .lstrip ()[0 ] == "@" :
696+ annotations .append (last_line )
697+ last_line = lines .pop ()
698+ if last_line .strip () == "*/" :
699+ first = True
700+ for content_line in content :
701+ if first :
702+ lines .append (
703+ indent
704+ + " * @"
705+ + javadoc_type
706+ + " "
707+ + content_line
708+ + "\n "
709+ )
710+ first = False
711+ else :
712+ lines .append (indent + " * " + content_line + "\n " )
713+ lines .append (last_line )
714+ else :
715+ lines .append (last_line )
716+ lines .append (indent + "/**\n " )
717+ first = True
718+ for content_line in content :
719+ if first :
720+ lines .append (
721+ indent
722+ + " * @"
723+ + javadoc_type
724+ + " "
725+ + content_line
726+ + "\n "
727+ )
728+ first = False
729+ else :
730+ lines .append (indent + " * " + content_line + "\n " )
731+ lines .append (indent + " */\n " )
732+ lines .extend (annotations [::- 1 ])
733+ lines .append (line )
734+ line = fp .readline ()
735+
736+ with open (filename , "w" ) as fp :
737+ for line in lines :
738+ # print(line)
739+ fp .write (line )
740+
741+
742+ def annotate_method (filename : str , signature : str , annotation : str ):
743+ """Helper to add an annotation to a method.
744+
745+ Goes line-by-line to detect the start of the block.
746+ Then adds the annotation above the found method signature.
747+
748+ Example: consider the following class:
749+
750+ class Example {
751+ public void main(String[] args) {
752+ System.out.println("Hello World");
753+ }
754+
755+ public String foo() {
756+ return "bar";
757+ }
758+ }
759+
760+ To add an annotation the `main` method above, use:
761+
762+ annotate_method('path/to/file', 'public void main(String[] args)',
763+ '@Generated()')
764+
765+ Args:
766+ filename (str): Path to source file
767+ signature (str): Full signature of the method to remove. Example:
768+ `public void main(String[] args)`.
769+ annotation (str): Full annotation. Example: `@Deprecated`
770+ """
771+ lines : List [str ] = []
772+ with open (filename , "r" ) as fp :
773+ line = fp .readline ()
774+ while line :
775+ # for each line, try to find the matching
776+ regex = re .compile ("(\\ s*)" + re .escape (signature ) + ".*" )
777+ match = regex .match (line )
778+ if match :
779+ leading_spaces = len (line ) - len (line .lstrip ())
780+ indent = leading_spaces * " "
781+ lines .append (indent + annotation + "\n " )
782+ lines .append (line )
783+ line = fp .readline ()
784+
785+ with open (filename , "w" ) as fp :
786+ for line in lines :
787+ # print(line)
788+ fp .write (line )
789+
790+
791+ def deprecate_method (filename : str , signature : str , alternative : str ):
792+ """Helper to deprecate a method.
793+
794+ Goes line-by-line to detect the start of the block.
795+ Then adds the deprecation comment before the method signature.
796+ The @Deprecation annotation is also added.
797+
798+ Example: consider the following class:
799+
800+ class Example {
801+ public void main(String[] args) {
802+ System.out.println("Hello World");
803+ }
804+
805+ public String foo() {
806+ return "bar";
807+ }
808+ }
809+
810+ To deprecate the `main` method above, use:
811+
812+ deprecate_method('path/to/file', 'public void main(String[] args)',
813+ DEPRECATION_WARNING.format(new_method="foo"))
814+
815+ Args:
816+ filename (str): Path to source file
817+ signature (str): Full signature of the method to remove. Example:
818+ `public void main(String[] args)`.
819+ alternative: DEPRECATION WARNING: multiline javadoc comment with user
820+ specified leading open/close comment tags
821+ """
822+ add_javadoc (filename , signature , "deprecated" , alternative .splitlines ())
823+ annotate_method (filename , signature , "@Deprecated" )
0 commit comments