From e19a7e7e66072029ce7ed70d865371b3cb021649 Mon Sep 17 00:00:00 2001 From: aclement Date: Mon, 20 Oct 2008 04:38:51 +0000 Subject: [PATCH] 251277: making asmmanager non-singleton --- .../aspectj/tools/ajdoc/CompilerWrapper.java | 15 +- .../aspectj/tools/ajdoc/HtmlDecorator.java | 12 +- ajdoc/src/org/aspectj/tools/ajdoc/Main.java | 1347 ++++++++--------- .../aspectj/tools/ajdoc/StructureUtil.java | 155 +- .../tools/ajdoc/StubFileGenerator.java | 349 +++-- 5 files changed, 927 insertions(+), 951 deletions(-) diff --git a/ajdoc/src/org/aspectj/tools/ajdoc/CompilerWrapper.java b/ajdoc/src/org/aspectj/tools/ajdoc/CompilerWrapper.java index cf8c15edf..f27d3b166 100644 --- a/ajdoc/src/org/aspectj/tools/ajdoc/CompilerWrapper.java +++ b/ajdoc/src/org/aspectj/tools/ajdoc/CompilerWrapper.java @@ -9,8 +9,9 @@ * Contributors: * Mik Kersten initial implementation * ******************************************************************/ - package org.aspectj.tools.ajdoc; +package org.aspectj.tools.ajdoc; +import org.aspectj.asm.AsmManager; import org.aspectj.bridge.IMessage; /** @@ -21,17 +22,17 @@ import org.aspectj.bridge.IMessage; public class CompilerWrapper extends org.aspectj.tools.ajc.Main { private static CompilerWrapper INSTANCE = null; - - public static void main(String[] args) { - INSTANCE = new CompilerWrapper(); + + public static AsmManager executeMain(String[] args) { + INSTANCE = new CompilerWrapper(); INSTANCE.runMain(args, true); + return AsmManager.lastActiveStructureModel; + } - } - public static boolean hasErrors() { return INSTANCE.ourHandler.getErrors().length > 0; } - + public static IMessage[] getErrors() { return INSTANCE.ourHandler.getErrors(); } diff --git a/ajdoc/src/org/aspectj/tools/ajdoc/HtmlDecorator.java b/ajdoc/src/org/aspectj/tools/ajdoc/HtmlDecorator.java index 12c994bcd..bad35529f 100644 --- a/ajdoc/src/org/aspectj/tools/ajdoc/HtmlDecorator.java +++ b/ajdoc/src/org/aspectj/tools/ajdoc/HtmlDecorator.java @@ -53,13 +53,13 @@ class HtmlDecorator { static File rootDir = null; static String docVisibilityModifier; - static void decorateHTMLFromInputFiles(Hashtable table, File newRootDir, File[] inputFiles, String docModifier) + static void decorateHTMLFromInputFiles(AsmManager model, Hashtable table, File newRootDir, File[] inputFiles, String docModifier) throws IOException { rootDir = newRootDir; declIDTable = table; docVisibilityModifier = docModifier; for (int i = 0; i < inputFiles.length; i++) { - decorateHTMLFromIPEs(getProgramElements(inputFiles[i].getCanonicalPath()), rootDir.getCanonicalPath() + decorateHTMLFromIPEs(getProgramElements(model, inputFiles[i].getCanonicalPath()), rootDir.getCanonicalPath() + Config.DIR_SEP_CHAR, docModifier, false); } } @@ -516,7 +516,7 @@ class HtmlDecorator { IProgramElement currDecl = null; if (o instanceof String) { String currHandle = (String) o; - currDecl = AsmManager.getDefault().getHierarchy().findElementForHandle(currHandle); + currDecl = node.getModel().getHierarchy().findElementForHandle(currHandle); } else if (o instanceof IProgramElement) { currDecl = (IProgramElement) o; } else { @@ -668,7 +668,7 @@ class HtmlDecorator { List addedNames = new ArrayList(); // for ensuring that we don't add duplciates for (Iterator it = targets.iterator(); it.hasNext();) { String currHandle = (String) it.next(); - IProgramElement currDecl = AsmManager.getDefault().getHierarchy().findElementForHandle(currHandle); + IProgramElement currDecl = decl.getModel().getHierarchy().findElementForHandle(currHandle); if (currDecl.getKind().equals(IProgramElement.Kind.CODE)) { currDecl = currDecl.getParent(); // promote to enclosing } @@ -850,9 +850,9 @@ class HtmlDecorator { return formattedComment; } - static public IProgramElement[] getProgramElements(String filename) { + static public IProgramElement[] getProgramElements(AsmManager model, String filename) { - IProgramElement file = (IProgramElement) AsmManager.getDefault().getHierarchy().findElementForSourceFile(filename); + IProgramElement file = (IProgramElement) model.getHierarchy().findElementForSourceFile(filename); final List nodes = new ArrayList(); HierarchyWalker walker = new HierarchyWalker() { public void preProcess(IProgramElement node) { diff --git a/ajdoc/src/org/aspectj/tools/ajdoc/Main.java b/ajdoc/src/org/aspectj/tools/ajdoc/Main.java index a69dbc1d5..15c4301e1 100644 --- a/ajdoc/src/org/aspectj/tools/ajdoc/Main.java +++ b/ajdoc/src/org/aspectj/tools/ajdoc/Main.java @@ -14,400 +14,405 @@ package org.aspectj.tools.ajdoc; -import java.io.*; -import java.util.*; - +import java.io.BufferedReader; +import java.io.File; import java.io.FileFilter; - +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.aspectj.asm.AsmManager; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.Version; import org.aspectj.util.FileUtil; /** - * This is an old implementation of ajdoc that does not use an OO style. However, it - * does the job, and should serve to evolve a lightweight ajdoc implementation until - * we can make a properly extended javadoc implementation. + * This is an old implementation of ajdoc that does not use an OO style. However, it does the job, and should serve to evolve a + * lightweight ajdoc implementation until we can make a properly extended javadoc implementation. * * @author Mik Kersten */ public class Main implements Config { - private static final String FAIL_MESSAGE = "> compile failed, exiting ajdoc"; + private static final String FAIL_MESSAGE = "> compile failed, exiting ajdoc"; + + /** Command line options. */ + static Vector options; - /** Command line options. */ - static Vector options; + /** Options to pass to ajc. */ + static Vector ajcOptions; - /** Options to pass to ajc. */ - static Vector ajcOptions; + /** All of the files to be processed by ajdoc. */ + static Vector filenames; - /** All of the files to be processed by ajdoc. */ - static Vector filenames; + /** List of files to pass to javadoc. */ + static Vector fileList; - /** List of files to pass to javadoc. */ - static Vector fileList; + /** List of packages to pass to javadoc. */ + static Vector packageList; - /** List of packages to pass to javadoc. */ - static Vector packageList; + /** Default to package visiblity. */ + static String docModifier = "package"; - /** Default to package visiblity. */ - static String docModifier = "package"; + static Vector sourcepath; - static Vector sourcepath; + static boolean verboseMode = false; + static boolean packageMode = false; + static boolean authorStandardDocletSwitch = false; + static boolean versionStandardDocletSwitch = false; + static File rootDir = null; + static Hashtable declIDTable = new Hashtable(); + static String docDir = "."; + + private static boolean deleteTempFilesOnExit = true; - static boolean verboseMode = false; - static boolean packageMode = false; - static boolean authorStandardDocletSwitch = false; - static boolean versionStandardDocletSwitch = false; - static File rootDir = null; - static Hashtable declIDTable = new Hashtable(); - static String docDir = "."; - - private static boolean deleteTempFilesOnExit = true; - private static boolean aborted = false; private static IMessage[] errors; private static boolean shownAjdocUsageMessage = false; - + // creating a local variable to enable us to create the ajdocworkingdir // in a local sandbox during testing private static String outputWorkingDir = Config.WORKING_DIR; - public static void clearState() { - options = new Vector(); - ajcOptions = new Vector(); - filenames = new Vector(); - fileList= new Vector(); - packageList = new Vector(); - docModifier = "package"; - sourcepath = new Vector(); - verboseMode = false; - packageMode = false; - rootDir = null; - declIDTable = new Hashtable(); - docDir = "."; - aborted = false; - deleteTempFilesOnExit = true; - } - - public static void main(String[] args) { - clearState(); - if (!JavadocRunner.has14ToolsAvailable()) { - System.err.println("ajdoc requires a JDK 1.4 or later tools jar - exiting"); - aborted = true; - return; - } - - // STEP 1: parse the command line and do other global setup - sourcepath.addElement("."); // add the current directory to the classapth - parseCommandLine(args); - rootDir = getRootDir(); - File[] inputFiles = new File[filenames.size()]; - File[] signatureFiles = new File[filenames.size()]; - try { - // create the workingdir if it doesn't exist - if ( !(new File( outputWorkingDir ).isDirectory()) ) { - File dir = new File( outputWorkingDir ); - dir.mkdir(); - if (deleteTempFilesOnExit) dir.deleteOnExit(); - } - - for (int i = 0; i < filenames.size(); i++) { - inputFiles[i] = new File((String)filenames.elementAt(i)); - } - - // PHASE 0: call ajc - callAjc(inputFiles); - if (CompilerWrapper.hasErrors()) { - System.out.println(FAIL_MESSAGE); - aborted = true; - errors = CompilerWrapper.getErrors(); - return; - } - - for (int ii = 0; ii < filenames.size(); ii++) { - signatureFiles[ii] = createSignatureFile(inputFiles[ii]); - } - - // PHASE 1: generate Signature files (Java with DeclIDs and no bodies). - System.out.println( "> Building signature files..." ); - try{ - StubFileGenerator.doFiles(declIDTable, inputFiles, signatureFiles); - } catch (DocException d){ + public static void clearState() { + options = new Vector(); + ajcOptions = new Vector(); + filenames = new Vector(); + fileList = new Vector(); + packageList = new Vector(); + docModifier = "package"; + sourcepath = new Vector(); + verboseMode = false; + packageMode = false; + rootDir = null; + declIDTable = new Hashtable(); + docDir = "."; + aborted = false; + deleteTempFilesOnExit = true; + } + + public static void main(String[] args) { + clearState(); + if (!JavadocRunner.has14ToolsAvailable()) { + System.err.println("ajdoc requires a JDK 1.4 or later tools jar - exiting"); + aborted = true; + return; + } + + // STEP 1: parse the command line and do other global setup + sourcepath.addElement("."); // add the current directory to the classapth + parseCommandLine(args); + rootDir = getRootDir(); + File[] inputFiles = new File[filenames.size()]; + File[] signatureFiles = new File[filenames.size()]; + try { + // create the workingdir if it doesn't exist + if (!(new File(outputWorkingDir).isDirectory())) { + File dir = new File(outputWorkingDir); + dir.mkdir(); + if (deleteTempFilesOnExit) + dir.deleteOnExit(); + } + + for (int i = 0; i < filenames.size(); i++) { + inputFiles[i] = new File((String) filenames.elementAt(i)); + } + + // PHASE 0: call ajc + AsmManager model = callAjc(inputFiles); + if (CompilerWrapper.hasErrors()) { + System.out.println(FAIL_MESSAGE); + aborted = true; + errors = CompilerWrapper.getErrors(); + return; + } + + for (int ii = 0; ii < filenames.size(); ii++) { + signatureFiles[ii] = createSignatureFile(model, inputFiles[ii]); + } + + // PHASE 1: generate Signature files (Java with DeclIDs and no bodies). + System.out.println("> Building signature files..."); + try { + StubFileGenerator.doFiles(model, declIDTable, inputFiles, signatureFiles); + } catch (DocException d) { System.err.println(d.getMessage()); return; } - // PHASE 2: let Javadoc generate HTML (with DeclIDs) + // PHASE 2: let Javadoc generate HTML (with DeclIDs) callJavadoc(signatureFiles); - // PHASE 3: add AspectDoc specific stuff to the HTML (and remove the DeclIDS). - decorateHtmlFiles(inputFiles); - System.out.println( "> Finished." ); - } catch (Throwable e) { - handleInternalError(e); - exit(-2); - } - } - - private static void callAjc(File[] inputFiles) { - ajcOptions.addElement("-noExit"); - ajcOptions.addElement("-XjavadocsInModel"); // TODO: wrong option to force model gen - ajcOptions.addElement("-d"); - ajcOptions.addElement(rootDir.getAbsolutePath()); + // PHASE 3: add AspectDoc specific stuff to the HTML (and remove the DeclIDS). + decorateHtmlFiles(model, inputFiles); + System.out.println("> Finished."); + } catch (Throwable e) { + handleInternalError(e); + exit(-2); + } + } + + private static AsmManager callAjc(File[] inputFiles) { + ajcOptions.addElement("-noExit"); + ajcOptions.addElement("-XjavadocsInModel"); // TODO: wrong option to force model gen + ajcOptions.addElement("-d"); + ajcOptions.addElement(rootDir.getAbsolutePath()); String[] argsToCompiler = new String[ajcOptions.size() + inputFiles.length]; - int i = 0; - for ( ; i < ajcOptions.size(); i++ ) { - argsToCompiler[i] = (String)ajcOptions.elementAt(i); - } - for ( int j = 0; j < inputFiles.length; j++) { - argsToCompiler[i] = inputFiles[j].getAbsolutePath(); - //System.out.println(">> file to ajc: " + inputFiles[j].getAbsolutePath()); - i++; - } - System.out.println( "> Calling ajc..." ); - CompilerWrapper.main(argsToCompiler); - } - - private static void callJavadoc(File[] signatureFiles) throws IOException { - System.out.println( "> Calling javadoc..." ); - String[] javadocargs = null; - if ( packageMode ) { - int numExtraArgs = 2; - if (authorStandardDocletSwitch) numExtraArgs++; - if (versionStandardDocletSwitch) numExtraArgs++; - javadocargs = new String[numExtraArgs + options.size() + packageList.size() + - fileList.size() ]; - javadocargs[0] = "-sourcepath"; - javadocargs[1] = outputWorkingDir; - int argIndex = 2; - if (authorStandardDocletSwitch) { - javadocargs[argIndex] = "-author"; - argIndex++; - } - if (versionStandardDocletSwitch) { - javadocargs[argIndex] = "-version"; - } - //javadocargs[1] = getSourcepathAsString(); - for (int k = 0; k < options.size(); k++) { - javadocargs[numExtraArgs+k] = (String)options.elementAt(k); - } - for (int k = 0; k < packageList.size(); k++) { - javadocargs[numExtraArgs+options.size() + k] = (String)packageList.elementAt(k); - } - for (int k = 0; k < fileList.size(); k++) { - javadocargs[numExtraArgs+options.size() + packageList.size() + k] = (String)fileList.elementAt(k); - } - } - else { - javadocargs = new String[options.size() + signatureFiles.length]; - for (int k = 0; k < options.size(); k++) { - javadocargs[k] = (String)options.elementAt(k); - } - for (int k = 0; k < signatureFiles.length; k++) { - javadocargs[options.size() + k] = StructureUtil.translateAjPathName(signatureFiles[k].getCanonicalPath()); - } - } - - JavadocRunner.callJavadoc(javadocargs); - } - - /** - * We start with the known HTML files (the ones that correspond directly to the - * input files.) As we go along, we may learn that Javadoc split one .java file - * into multiple .html files to handle inner classes or local classes. The html - * file decorator picks that up. - */ - private static void decorateHtmlFiles(File[] inputFiles) throws IOException { - System.out.println( "> Decorating html files..." ); - HtmlDecorator.decorateHTMLFromInputFiles(declIDTable, - rootDir, - inputFiles, - docModifier); - - System.out.println( "> Removing generated tags..." ); - removeDeclIDsFromFile("index-all.html", true); - removeDeclIDsFromFile("serialized-form.html", true); - if (packageList.size() > 0) { - for (int p = 0; p < packageList.size(); p++) { - removeDeclIDsFromFile(((String)packageList.elementAt(p)).replace('.','/') + - Config.DIR_SEP_CHAR + - "package-summary.html", true); - } - } else { + int i = 0; + for (; i < ajcOptions.size(); i++) { + argsToCompiler[i] = (String) ajcOptions.elementAt(i); + } + for (int j = 0; j < inputFiles.length; j++) { + argsToCompiler[i] = inputFiles[j].getAbsolutePath(); + // System.out.println(">> file to ajc: " + inputFiles[j].getAbsolutePath()); + i++; + } + System.out.println("> Calling ajc..."); + return CompilerWrapper.executeMain(argsToCompiler); + } + + private static void callJavadoc(File[] signatureFiles) throws IOException { + System.out.println("> Calling javadoc..."); + String[] javadocargs = null; + if (packageMode) { + int numExtraArgs = 2; + if (authorStandardDocletSwitch) + numExtraArgs++; + if (versionStandardDocletSwitch) + numExtraArgs++; + javadocargs = new String[numExtraArgs + options.size() + packageList.size() + fileList.size()]; + javadocargs[0] = "-sourcepath"; + javadocargs[1] = outputWorkingDir; + int argIndex = 2; + if (authorStandardDocletSwitch) { + javadocargs[argIndex] = "-author"; + argIndex++; + } + if (versionStandardDocletSwitch) { + javadocargs[argIndex] = "-version"; + } + // javadocargs[1] = getSourcepathAsString(); + for (int k = 0; k < options.size(); k++) { + javadocargs[numExtraArgs + k] = (String) options.elementAt(k); + } + for (int k = 0; k < packageList.size(); k++) { + javadocargs[numExtraArgs + options.size() + k] = (String) packageList.elementAt(k); + } + for (int k = 0; k < fileList.size(); k++) { + javadocargs[numExtraArgs + options.size() + packageList.size() + k] = (String) fileList.elementAt(k); + } + } else { + javadocargs = new String[options.size() + signatureFiles.length]; + for (int k = 0; k < options.size(); k++) { + javadocargs[k] = (String) options.elementAt(k); + } + for (int k = 0; k < signatureFiles.length; k++) { + javadocargs[options.size() + k] = StructureUtil.translateAjPathName(signatureFiles[k].getCanonicalPath()); + } + } + + JavadocRunner.callJavadoc(javadocargs); + } + + /** + * We start with the known HTML files (the ones that correspond directly to the input files.) As we go along, we may learn that + * Javadoc split one .java file into multiple .html files to handle inner classes or local classes. The html file decorator + * picks that up. + */ + private static void decorateHtmlFiles(AsmManager model, File[] inputFiles) throws IOException { + System.out.println("> Decorating html files..."); + HtmlDecorator.decorateHTMLFromInputFiles(model, declIDTable, rootDir, inputFiles, docModifier); + + System.out.println("> Removing generated tags..."); + removeDeclIDsFromFile("index-all.html", true); + removeDeclIDsFromFile("serialized-form.html", true); + if (packageList.size() > 0) { + for (int p = 0; p < packageList.size(); p++) { + removeDeclIDsFromFile(((String) packageList.elementAt(p)).replace('.', '/') + Config.DIR_SEP_CHAR + + "package-summary.html", true); + } + } else { File[] files = rootDir.listFiles(); - if (files == null){ + if (files == null) { System.err.println("Destination directory is not a directory: " + rootDir.toString()); return; } - files = FileUtil.listFiles(rootDir, new FileFilter() { - public boolean accept(File f) { + files = FileUtil.listFiles(rootDir, new FileFilter() { + public boolean accept(File f) { return f.getName().equals("package-summary.html"); } - }); - for (int j = 0; j < files.length; j++) { - removeDeclIDsFromFile(files[j].getAbsolutePath(), false); - } - } - } - - private static void removeDeclIDsFromFile(String filename, boolean relativePath) { - // Remove the decl ids from "index-all.html" - File indexFile; - if (relativePath) { - indexFile = new File(docDir + Config.DIR_SEP_CHAR + filename); - } else { - indexFile = new File(filename); - } - try { - if ( indexFile.exists() ) { - BufferedReader indexFileReader = new BufferedReader( new FileReader( indexFile ) ); - // StringBuffer greatly reduces the time it takes to remove generated tags - StringBuffer indexFileBuffer = new StringBuffer((int)indexFile.length()); - String line = indexFileReader.readLine(); - while ( line != null ) { - int indexStart = line.indexOf( Config.DECL_ID_STRING ); - int indexEnd = line.indexOf( Config.DECL_ID_TERMINATOR ); - if ( indexStart != -1 && indexEnd != -1 ) { - line = line.substring( 0, indexStart ) + - line.substring( indexEnd+Config.DECL_ID_TERMINATOR.length() ); - } - indexFileBuffer.append(line); - line = indexFileReader.readLine(); - } - FileOutputStream fos = new FileOutputStream( indexFile ); - fos.write( indexFileBuffer.toString().getBytes() ); - - indexFileReader.close(); - fos.close(); - } - } - catch (IOException ioe) { - // be siltent - } - } - - static Vector getSourcePath() { - Vector sourcePath = new Vector(); - boolean found = false; - for ( int i = 0; i < options.size(); i++ ) { - String currOption = (String)options.elementAt(i); - if (found && !currOption.startsWith("-")) { - sourcePath.add(currOption); - } - if (currOption.equals("-sourcepath")) { - found = true; - } - } - return sourcePath; - } - - static File getRootDir() { - File rootDir = new File( "." ); - for ( int i = 0; i < options.size(); i++ ) { - if ( ((String)options.elementAt(i)).equals( "-d" ) ) { - rootDir = new File((String)options.elementAt(i+1)); - if ( !rootDir.exists() ) { - rootDir.mkdir(); -// System.out.println( "Destination directory not found: " + -// (String)options.elementAt(i+1) ); -// System.exit( -1 ); - } - } - } - return rootDir; - } - - static File createSignatureFile(File inputFile) throws IOException { - String packageName = StructureUtil.getPackageDeclarationFromFile(inputFile); - - String filename = ""; - if ( packageName != null ) { - String pathName = outputWorkingDir + '/' + packageName.replace('.', '/'); - File packageDir = new File(pathName); - if ( !packageDir.exists() ) { - packageDir.mkdirs(); - if (deleteTempFilesOnExit) packageDir.deleteOnExit(); - } - //verifyPackageDirExists(packageName, null); - packageName = packageName.replace( '.','/' ); // !!! - filename = outputWorkingDir + Config.DIR_SEP_CHAR + packageName + - Config.DIR_SEP_CHAR + inputFile.getName(); - } - else { - filename = outputWorkingDir + Config.DIR_SEP_CHAR + inputFile.getName(); - } - File signatureFile = new File( filename ); - if (deleteTempFilesOnExit) signatureFile.deleteOnExit(); - return signatureFile; - } - - -// static void verifyPackageDirExists( String packageName, String offset ) { -// System.err.println(">>> name: " + packageName + ", offset: " + offset); -// if ( packageName.indexOf( "." ) != -1 ) { -// File tempFile = new File("c:/aspectj-test/d1/d2/d3"); -// tempFile.mkdirs(); -// String currPkgDir = packageName.substring( 0, packageName.indexOf( "." ) ); -// String remainingPkg = packageName.substring( packageName.indexOf( "." )+1 ); -// String filePath = null; -// if ( offset != null ) { -// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + -// offset + Config.DIR_SEP_CHAR + currPkgDir ; -// } -// else { -// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + currPkgDir; -// } -// File packageDir = new File( filePath ); -// if ( !packageDir.exists() ) { -// packageDir.mkdir(); -// if (deleteTempFilesOnExit) packageDir.deleteOnExit(); -// } -// if ( remainingPkg != "" ) { -// verifyPackageDirExists( remainingPkg, currPkgDir ); -// } -// } -// else { -// String filePath = null; -// if ( offset != null ) { -// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + offset + Config.DIR_SEP_CHAR + packageName; -// } -// else { -// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + packageName; -// } -// File packageDir = new File( filePath ); -// if ( !packageDir.exists() ) { -// packageDir.mkdir(); -// if (deleteTempFilesOnExit) packageDir.deleteOnExit(); -// } -// } -// } - - /** - * Can read Eclipse-generated single-line arg - */ - static void parseCommandLine(String[] args) { - if (args.length == 0) { - displayHelpAndExit( null ); - } else if (args.length == 1 && args[0].startsWith("@")) { - String argFile = args[0].substring(1); - System.out.println("> Using arg file: " + argFile); - BufferedReader br; + }); + for (int j = 0; j < files.length; j++) { + removeDeclIDsFromFile(files[j].getAbsolutePath(), false); + } + } + } + + private static void removeDeclIDsFromFile(String filename, boolean relativePath) { + // Remove the decl ids from "index-all.html" + File indexFile; + if (relativePath) { + indexFile = new File(docDir + Config.DIR_SEP_CHAR + filename); + } else { + indexFile = new File(filename); + } + try { + if (indexFile.exists()) { + BufferedReader indexFileReader = new BufferedReader(new FileReader(indexFile)); + // StringBuffer greatly reduces the time it takes to remove generated tags + StringBuffer indexFileBuffer = new StringBuffer((int) indexFile.length()); + String line = indexFileReader.readLine(); + while (line != null) { + int indexStart = line.indexOf(Config.DECL_ID_STRING); + int indexEnd = line.indexOf(Config.DECL_ID_TERMINATOR); + if (indexStart != -1 && indexEnd != -1) { + line = line.substring(0, indexStart) + line.substring(indexEnd + Config.DECL_ID_TERMINATOR.length()); + } + indexFileBuffer.append(line); + line = indexFileReader.readLine(); + } + FileOutputStream fos = new FileOutputStream(indexFile); + fos.write(indexFileBuffer.toString().getBytes()); + + indexFileReader.close(); + fos.close(); + } + } catch (IOException ioe) { + // be siltent + } + } + + static Vector getSourcePath() { + Vector sourcePath = new Vector(); + boolean found = false; + for (int i = 0; i < options.size(); i++) { + String currOption = (String) options.elementAt(i); + if (found && !currOption.startsWith("-")) { + sourcePath.add(currOption); + } + if (currOption.equals("-sourcepath")) { + found = true; + } + } + return sourcePath; + } + + static File getRootDir() { + File rootDir = new File("."); + for (int i = 0; i < options.size(); i++) { + if (((String) options.elementAt(i)).equals("-d")) { + rootDir = new File((String) options.elementAt(i + 1)); + if (!rootDir.exists()) { + rootDir.mkdir(); + // System.out.println( "Destination directory not found: " + + // (String)options.elementAt(i+1) ); + // System.exit( -1 ); + } + } + } + return rootDir; + } + + static File createSignatureFile(AsmManager model, File inputFile) throws IOException { + String packageName = StructureUtil.getPackageDeclarationFromFile(model, inputFile); + + String filename = ""; + if (packageName != null) { + String pathName = outputWorkingDir + '/' + packageName.replace('.', '/'); + File packageDir = new File(pathName); + if (!packageDir.exists()) { + packageDir.mkdirs(); + if (deleteTempFilesOnExit) + packageDir.deleteOnExit(); + } + // verifyPackageDirExists(packageName, null); + packageName = packageName.replace('.', '/'); // !!! + filename = outputWorkingDir + Config.DIR_SEP_CHAR + packageName + Config.DIR_SEP_CHAR + inputFile.getName(); + } else { + filename = outputWorkingDir + Config.DIR_SEP_CHAR + inputFile.getName(); + } + File signatureFile = new File(filename); + if (deleteTempFilesOnExit) + signatureFile.deleteOnExit(); + return signatureFile; + } + + // static void verifyPackageDirExists( String packageName, String offset ) { + // System.err.println(">>> name: " + packageName + ", offset: " + offset); + // if ( packageName.indexOf( "." ) != -1 ) { + // File tempFile = new File("c:/aspectj-test/d1/d2/d3"); + // tempFile.mkdirs(); + // String currPkgDir = packageName.substring( 0, packageName.indexOf( "." ) ); + // String remainingPkg = packageName.substring( packageName.indexOf( "." )+1 ); + // String filePath = null; + // if ( offset != null ) { + // filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + + // offset + Config.DIR_SEP_CHAR + currPkgDir ; + // } + // else { + // filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + currPkgDir; + // } + // File packageDir = new File( filePath ); + // if ( !packageDir.exists() ) { + // packageDir.mkdir(); + // if (deleteTempFilesOnExit) packageDir.deleteOnExit(); + // } + // if ( remainingPkg != "" ) { + // verifyPackageDirExists( remainingPkg, currPkgDir ); + // } + // } + // else { + // String filePath = null; + // if ( offset != null ) { + // filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + offset + Config.DIR_SEP_CHAR + packageName; + // } + // else { + // filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + packageName; + // } + // File packageDir = new File( filePath ); + // if ( !packageDir.exists() ) { + // packageDir.mkdir(); + // if (deleteTempFilesOnExit) packageDir.deleteOnExit(); + // } + // } + // } + + /** + * Can read Eclipse-generated single-line arg + */ + static void parseCommandLine(String[] args) { + if (args.length == 0) { + displayHelpAndExit(null); + } else if (args.length == 1 && args[0].startsWith("@")) { + String argFile = args[0].substring(1); + System.out.println("> Using arg file: " + argFile); + BufferedReader br; try { br = new BufferedReader(new FileReader(argFile)); String line = ""; - line = br.readLine(); - StringTokenizer st = new StringTokenizer(line, " "); - List argList = new ArrayList(); - while(st.hasMoreElements()) { - argList.add(st.nextElement()); - } - //System.err.println(argList); - args = new String[argList.size()]; - int counter = 0; - for (Iterator it = argList.iterator(); it.hasNext(); ) { - args[counter] = (String)it.next(); - counter++; - } + line = br.readLine(); + StringTokenizer st = new StringTokenizer(line, " "); + List argList = new ArrayList(); + while (st.hasMoreElements()) { + argList.add(st.nextElement()); + } + // System.err.println(argList); + args = new String[argList.size()]; + int counter = 0; + for (Iterator it = argList.iterator(); it.hasNext();) { + args[counter] = (String) it.next(); + counter++; + } } catch (FileNotFoundException e) { System.err.println("> could not read arg file: " + argFile); e.printStackTrace(); @@ -415,359 +420,345 @@ public class Main implements Config { System.err.println("> could not read arg file: " + argFile); ioe.printStackTrace(); } - } - List vargs = new LinkedList(Arrays.asList(args)); - - parseArgs(vargs, new File( "." )); // !!! - - if (filenames.size() == 0) { - displayHelpAndExit( "ajdoc: No packages or classes specified" ); - } - } - - static void setSourcepath(String arg) { - sourcepath.clear(); - arg = arg + File.pathSeparator; // makes things easier for ourselves - StringTokenizer tokenizer = new StringTokenizer(arg, File.pathSeparator); - while (tokenizer.hasMoreElements()) { - sourcepath.addElement(tokenizer.nextElement()); - } - } - - static String getSourcepathAsString() { - String cPath = ""; - for (int i = 0; i < sourcepath.size(); i++) { - cPath += (String)sourcepath.elementAt(i) + Config.DIR_SEP_CHAR + outputWorkingDir; - if (i != sourcepath.size()-1) { - cPath += File.pathSeparator; - } - } - return cPath; - } - - static void parseArgs(List vargs, File currentWorkingDir) { - boolean addNextAsOption = false; - boolean addNextAsArgFile = false; - boolean addNextToAJCOptions = false; - boolean addNextAsDocDir = false; - boolean addNextAsClasspath = false; - boolean ignoreArg = false; // used for discrepancy betwen class/sourcepath in ajc/javadoc - boolean addNextAsSourcePath = false; - if ( vargs.size() == 0 ) { - displayHelpAndExit( null ); - } - for (int i = 0; i < vargs.size() ; i++) { - String arg = (String)vargs.get(i); - ignoreArg = false; - if (addNextAsDocDir) { - docDir = arg; - addNextAsDocDir = false; - } - if (addNextAsClasspath) { - addNextAsClasspath = false; - } - if (addNextAsSourcePath) { - setSourcepath( arg ); - addNextAsSourcePath = false; - ignoreArg = true; - } - - if ( arg.startsWith("@") ) { - expandAtSignFile(arg.substring(1), currentWorkingDir); - } else if ( arg.equals( "-argfile" ) ) { - addNextAsArgFile = true; - } else if ( addNextAsArgFile ) { - expandAtSignFile(arg, currentWorkingDir); - addNextAsArgFile = false; - } else if (arg.equals("-d") ) { - addNextAsOption = true; - options.addElement(arg); - addNextAsDocDir = true; - } else if ( arg.equals( "-bootclasspath" ) ) { - addNextAsOption = true; - addNextToAJCOptions = true; - options.addElement( arg ); - ajcOptions.addElement( arg ); - } else if ( arg.equals( "-source" ) ) { - addNextAsOption = true; - addNextToAJCOptions = true; - addNextAsClasspath = true; - options.addElement(arg); - ajcOptions.addElement(arg); - } else if ( arg.equals( "-classpath" ) ) { - addNextAsOption = true; - addNextToAJCOptions = true; - addNextAsClasspath = true; - options.addElement( arg ); - ajcOptions.addElement( arg ); - } else if ( arg.equals( "-encoding" ) ) { - addNextAsOption = true; - addNextToAJCOptions = false; - options.addElement( arg ); - } else if ( arg.equals( "-docencoding" ) ) { - addNextAsOption = true; - addNextToAJCOptions = false; - options.addElement( arg ); - } else if ( arg.equals( "-charset" ) ) { - addNextAsOption = true; - addNextToAJCOptions = false; - options.addElement( arg ); - } else if ( arg.equals( "-sourcepath" ) ) { - addNextAsSourcePath = true; - //options.addElement( arg ); - //ajcOptions.addElement( arg ); - } else if ( arg.equals( "-link" ) ) { - addNextAsOption = true; - options.addElement(arg); - } else if ( arg.equals( "-bottom" ) ) { - addNextAsOption = true; - options.addElement(arg); - } else if ( arg.equals( "-windowtitle" ) ) { - addNextAsOption = true; - options.addElement(arg); - } else if (arg.equals("-XajdocDebug")) { - deleteTempFilesOnExit = false; - } else if (arg.equals("-use")) { - System.out.println("> Ignoring unsupported option: -use"); - } else if (arg.equals("-splitindex")) { - // passed to javadoc - } else if (arg.startsWith("-") || addNextAsOption || addNextToAJCOptions) { - if ( arg.equals( "-private" ) ) { - docModifier = "private"; - } else if ( arg.equals( "-package" ) ) { - docModifier = "package"; - } else if ( arg.equals( "-protected" ) ) { - docModifier = "protected"; - } else if ( arg.equals( "-public" ) ) { - docModifier = "public"; - } else if ( arg.equals( "-verbose" ) ) { - verboseMode = true; - } else if ( arg.equals( "-author" ) ) { - authorStandardDocletSwitch = true; - } else if ( arg.equals( "-version" ) ) { - versionStandardDocletSwitch = true; - } else if ( arg.equals( "-v" ) ) { - System.out.println(getVersion()); - exit(0); - } else if ( arg.equals( "-help" ) ) { - displayHelpAndExit( null ); - } else if ( arg.equals( "-doclet" ) || arg.equals( "-docletpath" ) ) { - System.out.println( "The doclet and docletpath options are not currently supported \n" + - "since ajdoc makes assumptions about the behavior of the standard \n" + - "doclet. If you would find this option useful please email us at: \n" + - " \n" + - " aspectj-dev@eclipse.org \n" + - " \n" ); - exit(0); - } else if (arg.equals("-nonavbar") - || arg.equals("-noindex")) { - // pass through - //System.err.println("> ignoring unsupported option: " + arg); - } else if (addNextToAJCOptions || addNextAsOption) { - // deal with these two options together even though effectively - // just falling through if addNextAsOption is true. Otherwise - // will have to ensure check "addNextToAJCOptions" before - // "addNextAsOption" so as the options are added to the - // correct lists. - if (addNextToAJCOptions) { - ajcOptions.addElement(arg); - if (!arg.startsWith("-")) { - addNextToAJCOptions = false; - } - if (!addNextAsOption) { - continue; - } + } + List vargs = new LinkedList(Arrays.asList(args)); + + parseArgs(vargs, new File(".")); // !!! + + if (filenames.size() == 0) { + displayHelpAndExit("ajdoc: No packages or classes specified"); + } + } + + static void setSourcepath(String arg) { + sourcepath.clear(); + arg = arg + File.pathSeparator; // makes things easier for ourselves + StringTokenizer tokenizer = new StringTokenizer(arg, File.pathSeparator); + while (tokenizer.hasMoreElements()) { + sourcepath.addElement(tokenizer.nextElement()); + } + } + + static String getSourcepathAsString() { + String cPath = ""; + for (int i = 0; i < sourcepath.size(); i++) { + cPath += (String) sourcepath.elementAt(i) + Config.DIR_SEP_CHAR + outputWorkingDir; + if (i != sourcepath.size() - 1) { + cPath += File.pathSeparator; + } + } + return cPath; + } + + static void parseArgs(List vargs, File currentWorkingDir) { + boolean addNextAsOption = false; + boolean addNextAsArgFile = false; + boolean addNextToAJCOptions = false; + boolean addNextAsDocDir = false; + boolean addNextAsClasspath = false; + boolean ignoreArg = false; // used for discrepancy betwen class/sourcepath in ajc/javadoc + boolean addNextAsSourcePath = false; + if (vargs.size() == 0) { + displayHelpAndExit(null); + } + for (int i = 0; i < vargs.size(); i++) { + String arg = (String) vargs.get(i); + ignoreArg = false; + if (addNextAsDocDir) { + docDir = arg; + addNextAsDocDir = false; + } + if (addNextAsClasspath) { + addNextAsClasspath = false; + } + if (addNextAsSourcePath) { + setSourcepath(arg); + addNextAsSourcePath = false; + ignoreArg = true; + } + + if (arg.startsWith("@")) { + expandAtSignFile(arg.substring(1), currentWorkingDir); + } else if (arg.equals("-argfile")) { + addNextAsArgFile = true; + } else if (addNextAsArgFile) { + expandAtSignFile(arg, currentWorkingDir); + addNextAsArgFile = false; + } else if (arg.equals("-d")) { + addNextAsOption = true; + options.addElement(arg); + addNextAsDocDir = true; + } else if (arg.equals("-bootclasspath")) { + addNextAsOption = true; + addNextToAJCOptions = true; + options.addElement(arg); + ajcOptions.addElement(arg); + } else if (arg.equals("-source")) { + addNextAsOption = true; + addNextToAJCOptions = true; + addNextAsClasspath = true; + options.addElement(arg); + ajcOptions.addElement(arg); + } else if (arg.equals("-classpath")) { + addNextAsOption = true; + addNextToAJCOptions = true; + addNextAsClasspath = true; + options.addElement(arg); + ajcOptions.addElement(arg); + } else if (arg.equals("-encoding")) { + addNextAsOption = true; + addNextToAJCOptions = false; + options.addElement(arg); + } else if (arg.equals("-docencoding")) { + addNextAsOption = true; + addNextToAJCOptions = false; + options.addElement(arg); + } else if (arg.equals("-charset")) { + addNextAsOption = true; + addNextToAJCOptions = false; + options.addElement(arg); + } else if (arg.equals("-sourcepath")) { + addNextAsSourcePath = true; + // options.addElement( arg ); + // ajcOptions.addElement( arg ); + } else if (arg.equals("-link")) { + addNextAsOption = true; + options.addElement(arg); + } else if (arg.equals("-bottom")) { + addNextAsOption = true; + options.addElement(arg); + } else if (arg.equals("-windowtitle")) { + addNextAsOption = true; + options.addElement(arg); + } else if (arg.equals("-XajdocDebug")) { + deleteTempFilesOnExit = false; + } else if (arg.equals("-use")) { + System.out.println("> Ignoring unsupported option: -use"); + } else if (arg.equals("-splitindex")) { + // passed to javadoc + } else if (arg.startsWith("-") || addNextAsOption || addNextToAJCOptions) { + if (arg.equals("-private")) { + docModifier = "private"; + } else if (arg.equals("-package")) { + docModifier = "package"; + } else if (arg.equals("-protected")) { + docModifier = "protected"; + } else if (arg.equals("-public")) { + docModifier = "public"; + } else if (arg.equals("-verbose")) { + verboseMode = true; + } else if (arg.equals("-author")) { + authorStandardDocletSwitch = true; + } else if (arg.equals("-version")) { + versionStandardDocletSwitch = true; + } else if (arg.equals("-v")) { + System.out.println(getVersion()); + exit(0); + } else if (arg.equals("-help")) { + displayHelpAndExit(null); + } else if (arg.equals("-doclet") || arg.equals("-docletpath")) { + System.out.println("The doclet and docletpath options are not currently supported \n" + + "since ajdoc makes assumptions about the behavior of the standard \n" + + "doclet. If you would find this option useful please email us at: \n" + + " \n" + + " aspectj-dev@eclipse.org \n" + + " \n"); + exit(0); + } else if (arg.equals("-nonavbar") || arg.equals("-noindex")) { + // pass through + // System.err.println("> ignoring unsupported option: " + arg); + } else if (addNextToAJCOptions || addNextAsOption) { + // deal with these two options together even though effectively + // just falling through if addNextAsOption is true. Otherwise + // will have to ensure check "addNextToAJCOptions" before + // "addNextAsOption" so as the options are added to the + // correct lists. + if (addNextToAJCOptions) { + ajcOptions.addElement(arg); + if (!arg.startsWith("-")) { + addNextToAJCOptions = false; + } + if (!addNextAsOption) { + continue; + } } - } else if (arg.startsWith("-")) { - ajcOptions.addElement(arg); + } else if (arg.startsWith("-")) { + ajcOptions.addElement(arg); addNextToAJCOptions = true; continue; - } else { - System.err.println("> unrecognized argument: " + arg); - displayHelpAndExit( null ); - } - options.addElement(arg); - addNextAsOption = false; - } else { - // check if this is a file or a package -// System.err.println(">>>>>>>> " + ); -// String entryName = arg.substring(arg.lastIndexOf(File.separator)+1); - if (FileUtil.hasSourceSuffix(arg) || arg.endsWith(".lst") && arg != null ) { - File f = new File(arg); - if (f.isAbsolute()) { - filenames.addElement(arg); - } - else { - filenames.addElement( currentWorkingDir + Config.DIR_SEP_CHAR + arg ); - } - fileList.addElement( arg ); - } - - // PACKAGE MODE STUFF - else if (!ignoreArg) { - - packageMode = true; - packageList.addElement( arg ); - arg = arg.replace( '.', '/' ); // !!! - - // do this for every item in the classpath - for ( int c = 0; c < sourcepath.size(); c++ ) { - String path = (String)sourcepath.elementAt(c) + Config.DIR_SEP_CHAR + arg; - File pkg = new File(path); - if ( pkg.isDirectory() ) { - String[] files = pkg.list( new FilenameFilter() { - public boolean accept( File dir, String name ) { - int index1 = name.lastIndexOf( "." ); - int index2 = name.length(); - if ( (index1 >= 0 && index2 >= 0 ) && - (name.substring(index1, index2).equals( ".java" ) - || name.substring(index1, index2).equals( ".aj" ))) { - return true; - } - else { - return false; - } - } - } ); - for ( int j = 0; j < files.length; j++ ) { - filenames.addElement( (String)sourcepath.elementAt(c) + - Config.DIR_SEP_CHAR + - arg + Config.DIR_SEP_CHAR + files[j] ); - } - } - else if (c == sourcepath.size() ) { // last element on classpath - System.out.println( "ajdoc: No package, class, or source file " + - "found named " + arg + "." ); - } - else { - // didn't find it on that element of the classpath but that's ok - } - } - } - } - } - // set the default visibility as an option to javadoc option - if ( !options.contains( "-private" ) && - !options.contains( "-package" ) && - !options.contains( "-protected" ) && - !options.contains( "-public" ) ) { - options.addElement( "-package" ); - } - } - - static void expandAtSignFile(String filename, File currentWorkingDir) { - List result = new LinkedList(); - - File atFile = qualifiedFile(filename, currentWorkingDir); - String atFileParent = atFile.getParent(); - File myWorkingDir = null; - if (atFileParent != null) myWorkingDir = new File(atFileParent); - - try { - BufferedReader stream = new BufferedReader(new FileReader(atFile)); - String line = null; - while ( (line = stream.readLine()) != null) { - // strip out any comments of the form # to end of line - int commentStart = line.indexOf("//"); - if (commentStart != -1) { - line = line.substring(0, commentStart); - } - - // remove extra whitespace that might have crept in - line = line.trim(); - // ignore blank lines - if (line.length() == 0) continue; - result.add(line); - } - } catch (IOException e) { - System.err.println("Error while reading the @ file " + atFile.getPath() + ".\n" - + e); - System.exit( -1 ); - } - - parseArgs(result, myWorkingDir); - } - - static File qualifiedFile(String name, File currentWorkingDir) { - name = name.replace('/', File.separatorChar); - File file = new File(name); - if (!file.isAbsolute() && currentWorkingDir != null) { - file = new File(currentWorkingDir, name); - } - return file; - } - - - static void displayHelpAndExit(String message) { - shownAjdocUsageMessage = true; - if (message != null) { + } else { + System.err.println("> unrecognized argument: " + arg); + displayHelpAndExit(null); + } + options.addElement(arg); + addNextAsOption = false; + } else { + // check if this is a file or a package + // System.err.println(">>>>>>>> " + ); + // String entryName = arg.substring(arg.lastIndexOf(File.separator)+1); + if (FileUtil.hasSourceSuffix(arg) || arg.endsWith(".lst") && arg != null) { + File f = new File(arg); + if (f.isAbsolute()) { + filenames.addElement(arg); + } else { + filenames.addElement(currentWorkingDir + Config.DIR_SEP_CHAR + arg); + } + fileList.addElement(arg); + } + + // PACKAGE MODE STUFF + else if (!ignoreArg) { + + packageMode = true; + packageList.addElement(arg); + arg = arg.replace('.', '/'); // !!! + + // do this for every item in the classpath + for (int c = 0; c < sourcepath.size(); c++) { + String path = (String) sourcepath.elementAt(c) + Config.DIR_SEP_CHAR + arg; + File pkg = new File(path); + if (pkg.isDirectory()) { + String[] files = pkg.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + int index1 = name.lastIndexOf("."); + int index2 = name.length(); + if ((index1 >= 0 && index2 >= 0) + && (name.substring(index1, index2).equals(".java") || name.substring(index1, index2) + .equals(".aj"))) { + return true; + } else { + return false; + } + } + }); + for (int j = 0; j < files.length; j++) { + filenames.addElement((String) sourcepath.elementAt(c) + Config.DIR_SEP_CHAR + arg + + Config.DIR_SEP_CHAR + files[j]); + } + } else if (c == sourcepath.size()) { // last element on classpath + System.out.println("ajdoc: No package, class, or source file " + "found named " + arg + "."); + } else { + // didn't find it on that element of the classpath but that's ok + } + } + } + } + } + // set the default visibility as an option to javadoc option + if (!options.contains("-private") && !options.contains("-package") && !options.contains("-protected") + && !options.contains("-public")) { + options.addElement("-package"); + } + } + + static void expandAtSignFile(String filename, File currentWorkingDir) { + List result = new LinkedList(); + + File atFile = qualifiedFile(filename, currentWorkingDir); + String atFileParent = atFile.getParent(); + File myWorkingDir = null; + if (atFileParent != null) + myWorkingDir = new File(atFileParent); + + try { + BufferedReader stream = new BufferedReader(new FileReader(atFile)); + String line = null; + while ((line = stream.readLine()) != null) { + // strip out any comments of the form # to end of line + int commentStart = line.indexOf("//"); + if (commentStart != -1) { + line = line.substring(0, commentStart); + } + + // remove extra whitespace that might have crept in + line = line.trim(); + // ignore blank lines + if (line.length() == 0) + continue; + result.add(line); + } + } catch (IOException e) { + System.err.println("Error while reading the @ file " + atFile.getPath() + ".\n" + e); + System.exit(-1); + } + + parseArgs(result, myWorkingDir); + } + + static File qualifiedFile(String name, File currentWorkingDir) { + name = name.replace('/', File.separatorChar); + File file = new File(name); + if (!file.isAbsolute() && currentWorkingDir != null) { + file = new File(currentWorkingDir, name); + } + return file; + } + + static void displayHelpAndExit(String message) { + shownAjdocUsageMessage = true; + if (message != null) { System.err.println(message); System.err.println(); - System.err.println(Config.USAGE); - } else { + System.err.println(Config.USAGE); + } else { System.out.println(Config.USAGE); exit(0); - } - } - - static protected void exit(int value) { - System.out.flush(); - System.err.flush(); - System.exit(value); - } - - /* This section of code handles errors that occur during compilation */ - static final String internalErrorMessage = - " \n"+ - "If this has not already been logged as a bug raised please raise \n"+ - "a new AspectJ bug at https://bugs.eclipse.org/bugs including the \n"+ - "text below. To make the bug a priority, please also include a test\n"+ - "program that can reproduce this problem.\n "; - - static public void handleInternalError(Throwable uncaughtThrowable) { - System.err.println("An internal error occured in ajdoc"); - System.err.println(internalErrorMessage); - System.err.println(uncaughtThrowable.toString()); - uncaughtThrowable.printStackTrace(); - System.err.println(); - } - - static String getVersion() { - return "ajdoc version " + Version.text; - } - + } + } + + static protected void exit(int value) { + System.out.flush(); + System.err.flush(); + System.exit(value); + } + + /* This section of code handles errors that occur during compilation */ + static final String internalErrorMessage = " \n" + + "If this has not already been logged as a bug raised please raise \n" + + "a new AspectJ bug at https://bugs.eclipse.org/bugs including the \n" + + "text below. To make the bug a priority, please also include a test\n" + + "program that can reproduce this problem.\n "; + + static public void handleInternalError(Throwable uncaughtThrowable) { + System.err.println("An internal error occured in ajdoc"); + System.err.println(internalErrorMessage); + System.err.println(uncaughtThrowable.toString()); + uncaughtThrowable.printStackTrace(); + System.err.println(); + } + + static String getVersion() { + return "ajdoc version " + Version.text; + } + public static boolean hasAborted() { return aborted; } - + public static IMessage[] getErrors() { return errors; } - + public static boolean hasShownAjdocUsageMessage() { return shownAjdocUsageMessage; } - + /** - * Sets the output working dir to be \ajdocworkingdir - * Useful in testing to redirect the ajdocworkingdir to the sandbox + * Sets the output working dir to be \ajdocworkingdir Useful in testing to redirect the ajdocworkingdir + * to the sandbox */ public static void setOutputWorkingDir(String fullyQulifiedOutputDir) { if (fullyQulifiedOutputDir == null) { resetOutputWorkingDir(); } else { - outputWorkingDir = fullyQulifiedOutputDir + File.separatorChar + - Config.WORKING_DIR; + outputWorkingDir = fullyQulifiedOutputDir + File.separatorChar + Config.WORKING_DIR; } } - + /** - * Resets the output working dir to be the default which is - * \ajdocworkingdir + * Resets the output working dir to be the default which is \ajdocworkingdir */ public static void resetOutputWorkingDir() { outputWorkingDir = Config.WORKING_DIR; } } - - diff --git a/ajdoc/src/org/aspectj/tools/ajdoc/StructureUtil.java b/ajdoc/src/org/aspectj/tools/ajdoc/StructureUtil.java index 26ebbd260..e38538f20 100644 --- a/ajdoc/src/org/aspectj/tools/ajdoc/StructureUtil.java +++ b/ajdoc/src/org/aspectj/tools/ajdoc/StructureUtil.java @@ -9,7 +9,7 @@ * Contributors: * Mik Kersten initial implementation * ******************************************************************/ - package org.aspectj.tools.ajdoc; +package org.aspectj.tools.ajdoc; import java.io.File; import java.util.ArrayList; @@ -26,76 +26,71 @@ import org.aspectj.asm.IRelationship; public class StructureUtil { /** - * Calculate the targets for a given IProgramElement (and it's - * immediate children if its not a type or if the child is - * CODE) and relationship kind + * Calculate the targets for a given IProgramElement (and it's immediate children if its not a type or if the child is CODE) and + * relationship kind * - * @return null if a relationship of that kind is not found + * @return null if a relationship of that kind is not found */ - public static List /*String*/ getTargets(IProgramElement node, IRelationship.Kind kind) { - return getTargets(node,kind,null); + public static List /* String */getTargets(IProgramElement node, IRelationship.Kind kind) { + return getTargets(node, kind, null); } - + /** - * Calculate the targets for a given IProgramElement (and it's immediate - * children if its not a type or if the child is CODE) and relationship - * kind with the specified relationship name. + * Calculate the targets for a given IProgramElement (and it's immediate children if its not a type or if the child is CODE) and + * relationship kind with the specified relationship name. * * @return null if a relationship of that kind is not found */ - public static List /*String*/ getTargets(IProgramElement node, IRelationship.Kind kind, String relName) { + public static List /* String */getTargets(IProgramElement node, IRelationship.Kind kind, String relName) { List relations = new ArrayList(); - List rels = AsmManager.getDefault().getRelationshipMap().get(node); + List rels = node.getModel().getRelationshipMap().get(node); if (rels != null) { relations.addAll(rels); } - for (Iterator iter = node.getChildren().iterator(); iter.hasNext();) { + for (Iterator iter = node.getChildren().iterator(); iter.hasNext();) { IProgramElement child = (IProgramElement) iter.next(); // if we're not a type, or if we are and the child is code, then // we want to get the relationships for this child - this means that the // correct relationships appear against the type in the ajdoc - if (!node.getKind().isType() - || child.getKind().equals(IProgramElement.Kind.CODE) ) { - List childRelations = AsmManager.getDefault().getRelationshipMap().get(child); + if (!node.getKind().isType() || child.getKind().equals(IProgramElement.Kind.CODE)) { + List childRelations = node.getModel().getRelationshipMap().get(child); if (childRelations != null) { - for (Iterator iterator = childRelations.iterator(); iterator - .hasNext();) { + for (Iterator iterator = childRelations.iterator(); iterator.hasNext();) { IRelationship rel = (IRelationship) iterator.next(); if (!relations.contains(rel)) { relations.add(rel); } } - } + } } - } - if (relations == null || relations.isEmpty()) return null; - List targets = new ArrayList(); - for (Iterator it = relations.iterator(); it.hasNext(); ) { - IRelationship rtn = (IRelationship)it.next(); - if (rtn.getKind().equals(kind) - && ((relName != null && relName.equals(rtn.getName())) - || relName == null)){ - List targs = rtn.getTargets(); - for (Iterator iter = targs.iterator(); iter.hasNext();) { + } + if (relations == null || relations.isEmpty()) + return null; + List targets = new ArrayList(); + for (Iterator it = relations.iterator(); it.hasNext();) { + IRelationship rtn = (IRelationship) it.next(); + if (rtn.getKind().equals(kind) && ((relName != null && relName.equals(rtn.getName())) || relName == null)) { + List targs = rtn.getTargets(); + for (Iterator iter = targs.iterator(); iter.hasNext();) { String element = (String) iter.next(); if (!targets.contains(element)) { targets.add(element); } } - } - } - return targets; + } + } + return targets; } - - static List /*IProgramElement */ getDeclareInterTypeTargets(IProgramElement node, IProgramElement.Kind kind) { + + static List /* IProgramElement */getDeclareInterTypeTargets(IProgramElement node, IProgramElement.Kind kind) { List targets = new ArrayList(); - List stringTargets = StructureUtil.getTargets(node,IRelationship.Kind.DECLARE_INTER_TYPE); + List stringTargets = StructureUtil.getTargets(node, IRelationship.Kind.DECLARE_INTER_TYPE); if (stringTargets == null) { return null; } for (Iterator iter = stringTargets.iterator(); iter.hasNext();) { String element = (String) iter.next(); - IProgramElement ipe = AsmManager.getDefault().getHierarchy().findElementForHandle(element); + IProgramElement ipe = node.getModel().getHierarchy().findElementForHandle(element); if (ipe != null && ipe.getKind().equals(kind)) { targets.add(ipe); } @@ -103,41 +98,41 @@ public class StructureUtil { return targets; } - public static List/*String*/ getDeclareTargets(IProgramElement node) { - List relations = AsmManager.getDefault().getRelationshipMap().get(node); - List targets = null; - if (relations == null) return null; - for (Iterator it = relations.iterator(); it.hasNext(); ) { - IRelationship rtn = (IRelationship)it.next(); - if (rtn.getKind().isDeclareKind()) { - targets = rtn.getTargets(); - } - } + public static List/* String */getDeclareTargets(IProgramElement node) { + List relations = node.getModel().getRelationshipMap().get(node); + List targets = null; + if (relations == null) + return null; + for (Iterator it = relations.iterator(); it.hasNext();) { + IRelationship rtn = (IRelationship) it.next(); + if (rtn.getKind().isDeclareKind()) { + targets = rtn.getTargets(); + } + } return targets; } - - public static String getPackageDeclarationFromFile(File file) { - IProgramElement fileNode = (IProgramElement)AsmManager.getDefault().getHierarchy().findElementForSourceFile(file.getAbsolutePath()); - String packageName = ((IProgramElement)fileNode.getChildren().get(0)).getPackageName(); - return packageName; + + public static String getPackageDeclarationFromFile(AsmManager model, File file) { + IProgramElement fileNode = model.getHierarchy().findElementForSourceFile(file.getAbsolutePath()); + String packageName = ((IProgramElement) fileNode.getChildren().get(0)).getPackageName(); + return packageName; } - + public static String genSignature(IProgramElement node) { StringBuffer sb = new StringBuffer(); - + String accessibility = node.getAccessibility().toString(); if (!accessibility.equals("package")) { sb.append(accessibility); sb.append(' '); } - + String modifiers = ""; - for (Iterator modIt = node.getModifiers().iterator(); modIt.hasNext(); ) { + for (Iterator modIt = node.getModifiers().iterator(); modIt.hasNext();) { modifiers += modIt.next() + " "; } - - if (node.getKind().equals(IProgramElement.Kind.METHOD) || - node.getKind().equals(IProgramElement.Kind.FIELD)) { + + if (node.getKind().equals(IProgramElement.Kind.METHOD) || node.getKind().equals(IProgramElement.Kind.FIELD)) { sb.append(node.getCorrespondingType()); sb.append(' '); } @@ -146,23 +141,23 @@ public class StructureUtil { sb.append("class "); } else if (node.getKind().equals(IProgramElement.Kind.INTERFACE)) { sb.append("interface "); - } + } sb.append(node.getName()); - - if (node.getParameterTypes() != null ) { - sb.append('('); + + if (node.getParameterTypes() != null) { + sb.append('('); for (int i = 0; i < node.getParameterTypes().size(); i++) { - sb.append((String)node.getParameterTypes().get(i)); + sb.append((String) node.getParameterTypes().get(i)); sb.append(' '); - sb.append((String)node.getParameterNames().get(i)); - if (i < node.getParameterTypes().size()-1) { + sb.append((String) node.getParameterNames().get(i)); + if (i < node.getParameterTypes().size() - 1) { sb.append(", "); } } sb.append(')'); } - + return sb.toString(); } @@ -174,24 +169,24 @@ public class StructureUtil { // !!! using exceptions for logic, fix isIntName = false; } -// System.err.println(">>>>>>>> " + node.getName()); + // System.err.println(">>>>>>>> " + node.getName()); return isIntName || node.getName().startsWith("new "); -// return isIntName; -// if (!isIntName) { -// -// return node.getName().startsWith("new "); -// } else { -// return false; -// } + // return isIntName; + // if (!isIntName) { + // + // return node.getName().startsWith("new "); + // } else { + // return false; + // } } /** - * @return same path, but ending in ".java" instead of ".aj" + * @return same path, but ending in ".java" instead of ".aj" */ public static String translateAjPathName(String path) { - if (path.endsWith(".aj")) { - path = path.substring(0, path.lastIndexOf(".aj")) + ".java"; - } - return path; + if (path.endsWith(".aj")) { + path = path.substring(0, path.lastIndexOf(".aj")) + ".java"; + } + return path; } } diff --git a/ajdoc/src/org/aspectj/tools/ajdoc/StubFileGenerator.java b/ajdoc/src/org/aspectj/tools/ajdoc/StubFileGenerator.java index c0f154f1b..e07a294bb 100644 --- a/ajdoc/src/org/aspectj/tools/ajdoc/StubFileGenerator.java +++ b/ajdoc/src/org/aspectj/tools/ajdoc/StubFileGenerator.java @@ -14,7 +14,11 @@ package org.aspectj.tools.ajdoc; -import java.io.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; import java.util.Hashtable; import java.util.Iterator; import java.util.List; @@ -25,208 +29,193 @@ import org.aspectj.asm.IProgramElement; /** * @author Mik Kersten */ -class StubFileGenerator{ - - static Hashtable declIDTable = null; - - static void doFiles (Hashtable table, - File[] inputFiles, - File[] signatureFiles) throws DocException { - declIDTable = table; - for (int i = 0; i < inputFiles.length; i++) { - processFile(inputFiles[i], signatureFiles[i]); - } - } - - - static void processFile(File inputFile, File signatureFile) throws DocException { - try { - String path = StructureUtil.translateAjPathName(signatureFile.getCanonicalPath()); - PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(path))); - - String packageName = StructureUtil.getPackageDeclarationFromFile(inputFile); - - if (packageName != null && packageName != "") { - writer.println( "package " + packageName + ";" ); - } - - IProgramElement fileNode = (IProgramElement)AsmManager.getDefault().getHierarchy().findElementForSourceFile(inputFile.getAbsolutePath()); - for (Iterator it = fileNode.getChildren().iterator(); it.hasNext(); ) { - IProgramElement node = (IProgramElement)it.next(); - if (node.getKind().equals(IProgramElement.Kind.IMPORT_REFERENCE)) { - processImportDeclaration(node, writer); - } else { +class StubFileGenerator { + + static Hashtable declIDTable = null; + + static void doFiles(AsmManager model, Hashtable table, File[] inputFiles, File[] signatureFiles) throws DocException { + declIDTable = table; + for (int i = 0; i < inputFiles.length; i++) { + processFile(model, inputFiles[i], signatureFiles[i]); + } + } + + static void processFile(AsmManager model, File inputFile, File signatureFile) throws DocException { + try { + String path = StructureUtil.translateAjPathName(signatureFile.getCanonicalPath()); + PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(path))); + + String packageName = StructureUtil.getPackageDeclarationFromFile(model, inputFile); + + if (packageName != null && packageName != "") { + writer.println("package " + packageName + ";"); + } + + IProgramElement fileNode = model.getHierarchy().findElementForSourceFile(inputFile.getAbsolutePath()); + for (Iterator it = fileNode.getChildren().iterator(); it.hasNext();) { + IProgramElement node = (IProgramElement) it.next(); + if (node.getKind().equals(IProgramElement.Kind.IMPORT_REFERENCE)) { + processImportDeclaration(node, writer); + } else { try { - processTypeDeclaration(node, writer); - } catch (DocException d){ + processTypeDeclaration(node, writer); + } catch (DocException d) { throw new DocException("File name invalid: " + inputFile.toString()); } - } - } - - // if we got an error we don't want the contents of the file - writer.close(); - } catch (IOException e) { - System.err.println(e.getMessage()); - e.printStackTrace(); - } - } - - private static void processImportDeclaration(IProgramElement node, PrintWriter writer) throws IOException { - List imports = node.getChildren(); - for (Iterator i = imports.iterator(); i.hasNext();) { + } + } + + // if we got an error we don't want the contents of the file + writer.close(); + } catch (IOException e) { + System.err.println(e.getMessage()); + e.printStackTrace(); + } + } + + private static void processImportDeclaration(IProgramElement node, PrintWriter writer) throws IOException { + List imports = node.getChildren(); + for (Iterator i = imports.iterator(); i.hasNext();) { IProgramElement importNode = (IProgramElement) i.next(); writer.println(importNode.getSourceSignature()); - } - } - - private static void processTypeDeclaration(IProgramElement classNode, PrintWriter writer) throws DocException { - - String formalComment = addDeclID(classNode, classNode.getFormalComment()); - writer.println(formalComment); - - String signature = genSourceSignature(classNode);// StructureUtil.genSignature(classNode); - if (signature == null){ + } + } + + private static void processTypeDeclaration(IProgramElement classNode, PrintWriter writer) throws DocException { + + String formalComment = addDeclID(classNode, classNode.getFormalComment()); + writer.println(formalComment); + + String signature = genSourceSignature(classNode);// StructureUtil.genSignature(classNode); + if (signature == null) { throw new DocException("The java file is invalid"); } - -// System.err.println("######" + signature + ", " + classNode.getName()); - if (!StructureUtil.isAnonymous(classNode) && !classNode.getName().equals("")) { - writer.println(signature + " { " ); - processMembers(classNode.getChildren(), writer, classNode.getKind().equals(IProgramElement.Kind.INTERFACE)); - writer.println(); + + // System.err.println("######" + signature + ", " + classNode.getName()); + if (!StructureUtil.isAnonymous(classNode) && !classNode.getName().equals("")) { + writer.println(signature + " { "); + processMembers(classNode.getChildren(), writer, classNode.getKind().equals(IProgramElement.Kind.INTERFACE)); + writer.println(); writer.println("}"); - } - } + } + } - private static void processMembers(List/*IProgramElement*/ members, PrintWriter writer, boolean declaringTypeIsInterface) throws DocException { - for (Iterator it = members.iterator(); it.hasNext();) { + private static void processMembers(List/* IProgramElement */members, PrintWriter writer, boolean declaringTypeIsInterface) + throws DocException { + for (Iterator it = members.iterator(); it.hasNext();) { IProgramElement member = (IProgramElement) it.next(); - - if (member.getKind().isType()) { - if (!member.getParent().getKind().equals(IProgramElement.Kind.METHOD) - && !StructureUtil.isAnonymous(member)) {// don't print anonymous types -// System.err.println(">>>>>>>>>>>>>" + member.getName() + "<<<<" + member.getParent()); - processTypeDeclaration(member, writer); - } + + if (member.getKind().isType()) { + if (!member.getParent().getKind().equals(IProgramElement.Kind.METHOD) && !StructureUtil.isAnonymous(member)) {// don't + // print + // anonymous + // types + // System.err.println(">>>>>>>>>>>>>" + member.getName() + "<<<<" + member.getParent()); + processTypeDeclaration(member, writer); + } } else { - String formalComment = addDeclID(member, member.getFormalComment());; - writer.println(formalComment); - - String signature = ""; - if (!member.getKind().equals(IProgramElement.Kind.POINTCUT) - && !member.getKind().equals(IProgramElement.Kind.ADVICE)) { - signature = member.getSourceSignature();//StructureUtil.genSignature(member); - if (member.getKind().equals(IProgramElement.Kind.ENUM_VALUE)){ + String formalComment = addDeclID(member, member.getFormalComment()); + ; + writer.println(formalComment); + + String signature = ""; + if (!member.getKind().equals(IProgramElement.Kind.POINTCUT) + && !member.getKind().equals(IProgramElement.Kind.ADVICE)) { + signature = member.getSourceSignature();// StructureUtil.genSignature(member); + if (member.getKind().equals(IProgramElement.Kind.ENUM_VALUE)) { int index = members.indexOf(member); - if ((index + 1 < members.size()) && - ((IProgramElement)members.get(index+1)).getKind().equals(IProgramElement.Kind.ENUM_VALUE)){ + if ((index + 1 < members.size()) + && ((IProgramElement) members.get(index + 1)).getKind().equals(IProgramElement.Kind.ENUM_VALUE)) { // if the next member is also an ENUM_VALUE: signature = signature + ","; } else { signature = signature + ";"; } } - } - - if (member.getKind().isDeclare()) { -// System.err.println("> Skipping declare (ajdoc limitation): " + member.toLabelString()); - } else if (signature != null && - signature != "" && - !member.getKind().isInterTypeMember() && - !member.getKind().equals(IProgramElement.Kind.INITIALIZER) && - !StructureUtil.isAnonymous(member)) { - writer.print(signature); - } else { -// System.err.println(">> skipping: " + member.getKind()); - } - - if (member.getKind().equals(IProgramElement.Kind.METHOD) || - member.getKind().equals(IProgramElement.Kind.CONSTRUCTOR)) { - if (member.getParent().getKind().equals(IProgramElement.Kind.INTERFACE) || - signature.indexOf("abstract ") != -1) { - writer.println(";"); - } else { - writer.println(" { }"); - } - - } else if (member.getKind().equals(IProgramElement.Kind.FIELD)) { -// writer.println(";"); - } + } + + if (member.getKind().isDeclare()) { + // System.err.println("> Skipping declare (ajdoc limitation): " + member.toLabelString()); + } else if (signature != null && signature != "" && !member.getKind().isInterTypeMember() + && !member.getKind().equals(IProgramElement.Kind.INITIALIZER) && !StructureUtil.isAnonymous(member)) { + writer.print(signature); + } else { + // System.err.println(">> skipping: " + member.getKind()); + } + + if (member.getKind().equals(IProgramElement.Kind.METHOD) + || member.getKind().equals(IProgramElement.Kind.CONSTRUCTOR)) { + if (member.getParent().getKind().equals(IProgramElement.Kind.INTERFACE) || signature.indexOf("abstract ") != -1) { + writer.println(";"); + } else { + writer.println(" { }"); + } + + } else if (member.getKind().equals(IProgramElement.Kind.FIELD)) { + // writer.println(";"); + } } } - } - - /** - * Translates "aspect" to "class", as long as its not ".aspect" - */ - private static String genSourceSignature(IProgramElement classNode) { - String signature = classNode.getSourceSignature(); - if (signature != null){ + } + + /** + * Translates "aspect" to "class", as long as its not ".aspect" + */ + private static String genSourceSignature(IProgramElement classNode) { + String signature = classNode.getSourceSignature(); + if (signature != null) { int index = signature.indexOf("aspect"); - if (index == 0 || (index != -1 && signature.charAt(index-1) != '.') ) { - signature = signature.substring(0, index) + - "class " + - signature.substring(index + 6, signature.length()); + if (index == 0 || (index != -1 && signature.charAt(index - 1) != '.')) { + signature = signature.substring(0, index) + "class " + signature.substring(index + 6, signature.length()); } } - return signature; + return signature; + } + + static int nextDeclID = 0; + + static String addDeclID(IProgramElement decl, String formalComment) { + String declID = "" + ++nextDeclID; + declIDTable.put(declID, decl); + return addToFormal(formalComment, Config.DECL_ID_STRING + declID + Config.DECL_ID_TERMINATOR); + } + + /** + * We want to go: just before the first period just before the first @ just before the end of the comment + * + * Adds a place holder for the period ('#') if one will need to be replaced. + */ + static String addToFormal(String formalComment, String string) { + if (string == null || string.equals("")) { + return formalComment; + } + // boolean appendPeriod = true; + if ((formalComment == null) || formalComment.equals("")) { + // formalComment = "/**\n * . \n */\n"; + formalComment = "/**\n * \n */\n"; + // appendPeriod = false; + } + formalComment = formalComment.trim(); + + int atsignPos = formalComment.indexOf('@'); + int endPos = formalComment.indexOf("*/"); + int periodPos = formalComment.indexOf("/**"); + int position = 0; + String periodPlaceHolder = ""; + if (periodPos != -1) { + position = periodPos + 3;// length of "/**" + } else if (atsignPos != -1) { + string = string + "\n * "; + position = atsignPos; + } else if (endPos != -1) { + string = "* " + string + "\n"; + position = endPos; + } else { + // !!! perhaps this error should not be silent + throw new Error("Failed to append to formal comment for comment: " + formalComment); + } + + return formalComment.substring(0, position) + periodPlaceHolder + string + formalComment.substring(position); } - - static int nextDeclID = 0; - static String addDeclID(IProgramElement decl, String formalComment) { - String declID = "" + ++nextDeclID; - declIDTable.put(declID, decl); - return addToFormal(formalComment, Config.DECL_ID_STRING + declID + Config.DECL_ID_TERMINATOR); - } - - /** - * We want to go: - * just before the first period - * just before the first @ - * just before the end of the comment - * - * Adds a place holder for the period ('#') if one will need to be - * replaced. - */ - static String addToFormal(String formalComment, String string) { - if(string == null || string.equals("")) { - return formalComment; - } - //boolean appendPeriod = true; - if ( (formalComment == null) || formalComment.equals("")) { - //formalComment = "/**\n * . \n */\n"; - formalComment = "/**\n * \n */\n"; - //appendPeriod = false; - } - formalComment = formalComment.trim(); - - int atsignPos = formalComment.indexOf('@'); - int endPos = formalComment.indexOf("*/"); - int periodPos = formalComment.indexOf("/**"); - int position = 0; - String periodPlaceHolder = ""; - if ( periodPos != -1 ) { - position = periodPos + 3;// length of "/**" - } - else if ( atsignPos != -1 ) { - string = string + "\n * "; - position = atsignPos; - } - else if ( endPos != -1 ) { - string = "* " + string + "\n"; - position = endPos; - } - else { - // !!! perhaps this error should not be silent - throw new Error("Failed to append to formal comment for comment: " + - formalComment ); - } - - return - formalComment.substring(0, position) + periodPlaceHolder + - string + - formalComment.substring(position); - } } -- 2.39.5