This is an automated email from the ASF dual-hosted git repository. aharui pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
commit 6163c0d4bd0b7afc78f12d4aeec18d4b6412b0ce Author: Alex Harui <aha...@apache.org> AuthorDate: Tue Feb 20 19:54:42 2018 -0800 first cut at api report --- .../royale/compiler/config/Configuration.java | 22 ++++++ .../org/apache/royale/compiler/clients/MXMLC.java | 3 +- .../compiler/internal/projects/RoyaleProject.java | 87 ++++++++++++++++++++++ .../compiler/internal/tree/as/IdentifierNode.java | 39 ++++++++++ 4 files changed, 150 insertions(+), 1 deletion(-) diff --git a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java index 226b7e6..8c3d8ed 100644 --- a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java +++ b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java @@ -500,6 +500,28 @@ public class Configuration this.sizeReportFileName = getOutputPath(cv, filename); } + // 'api-report' option + // + + private String apiReportFileName = null; + + public File getApiReport() + { + return apiReportFileName != null ? new File(apiReportFileName) : null; + } + + /** + * Prints api usage information to the specified output file. This file is an text file that contains every method and property + * resolved by the compiler. + */ + @Config(advanced = true) + @Mapping("api-report") + @Arguments("filename") + public void setApiReport(ConfigurationValue cv, String filename) + { + this.apiReportFileName = getOutputPath(cv, filename); + } + // // 'load-externs' option // diff --git a/compiler/src/main/java/org/apache/royale/compiler/clients/MXMLC.java b/compiler/src/main/java/org/apache/royale/compiler/clients/MXMLC.java index a6f7353..d83792b 100644 --- a/compiler/src/main/java/org/apache/royale/compiler/clients/MXMLC.java +++ b/compiler/src/main/java/org/apache/royale/compiler/clients/MXMLC.java @@ -503,6 +503,7 @@ public class MXMLC implements FlexTool // Get the configuration and configBuffer which are now initialized. config = projectConfigurator.getConfiguration(); Messages.setLocale(config.getToolsLocale()); + project.apiReportFile = config.getApiReport(); configBuffer = projectConfigurator.getConfigurationBuffer(); problems.addAll(projectConfigurator.getConfigurationProblems()); @@ -649,7 +650,7 @@ public class MXMLC implements FlexTool swfOutputMessage = Messages.getString("MXMLC.bytes_written_to_file_in_seconds_format", params); dumpDependencyGraphIfNeeded(); - + project.generateAPIReport(); compilationSuccess = true; } catch (IOException e) diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java index d4ea670..2182ecd 100644 --- a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java +++ b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java @@ -22,6 +22,8 @@ package org.apache.royale.compiler.internal.projects; import static com.google.common.collect.Lists.transform; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -1349,7 +1351,11 @@ public class RoyaleProject extends ASProject implements IRoyaleProject, ICompile } } if (winner != null) + { + if (apiReportFile != null) + addToAPIReport(classDefinition, winner); return winner; + } } } @@ -1372,7 +1378,11 @@ public class RoyaleProject extends ASProject implements IRoyaleProject, ICompile IClassDefinition c = classIterator.next(); IEventDefinition eventDefinition = c.getEventDefinition(getWorkspace(), eventName); if (eventDefinition != null) + { + if (apiReportFile != null) + addToAPIReport(classDefinition, eventDefinition); return eventDefinition; + } } return null; @@ -1396,7 +1406,11 @@ public class RoyaleProject extends ASProject implements IRoyaleProject, ICompile IClassDefinition c = classIterator.next(); IStyleDefinition styleDefinition = c.getStyleDefinition(w, styleName); if (styleDefinition != null) + { + if (apiReportFile != null) + addToAPIReport(classDefinition, styleDefinition); return styleDefinition; + } } return null; @@ -2369,4 +2383,77 @@ public class RoyaleProject extends ASProject implements IRoyaleProject, ICompile return true; } + public File apiReportFile; + + HashMap<String, Integer> apiMap = new HashMap<String, Integer>(); + + public void generateAPIReport() throws IOException + { + if (apiReportFile == null) + return; + + StringBuilder sb = new StringBuilder(); + Set<String> keys = apiMap.keySet(); + ArrayList<String> list = new ArrayList<String>(); + list.addAll(keys); + Collections.sort(list); + for (String key : list) + { + sb.append(key); + sb.append(","); + sb.append(apiMap.get(key).toString()); + sb.append("\n"); + } + + if (!apiReportFile.exists()) { + apiReportFile.createNewFile(); + } + + FileWriter fw = new FileWriter(apiReportFile, false); + fw.write(sb.toString()); + fw.close(); + } + + public void addToAPIReport(IClassDefinition c, IDefinition def) + { + String cqname = c.getQualifiedName(); + String qname = cqname + ":" + def.getQualifiedName(); + if (!apiMap.containsKey(qname)) + { + apiMap.put(qname, new Integer(1)); + return; + } + else + { + Integer counter = apiMap.get(qname); + int newCounter = counter.intValue() + 1; + apiMap.put(qname, new Integer(newCounter)); + } + } + + public void addToAPIReport(IDefinition def) + { + IDefinition parentDef = def.getParent(); + if (parentDef instanceof IClassDefinition) + addToAPIReport((IClassDefinition)parentDef, def); + else if (parentDef instanceof IFunctionDefinition) + { + // do nothing, local variable? + } + else + { + String qname = def.getQualifiedName(); + if (!apiMap.containsKey(qname)) + { + apiMap.put(qname, new Integer(1)); + return; + } + else + { + Integer counter = apiMap.get(qname); + int newCounter = counter.intValue() + 1; + apiMap.put(qname, new Integer(newCounter)); + } + } + } } diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java index 122b54b..f4a3689 100644 --- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java +++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java @@ -418,6 +418,45 @@ public class IdentifierNode extends ExpressionNodeBase implements IIdentifierNod } } + if (((RoyaleProject)project).apiReportFile != null) + { + if (isMemberRef()) + { + // if member ref, try to resolve the left side, because otherwise the parent definition + // will be the class that defined this property like ListCollectionView.sort instead + // of the subclass the developer was using on, like ArrayCollection. We want to log + // ArrayCollection.sort in case we don't need to implement full class hierarchy. + // A Royale ArrayCollection might not have to subclass ListCollectionView + if (parent.getNodeID() == ASTNodeID.MemberAccessExpressionID) + { + MemberAccessExpressionNode mae = (MemberAccessExpressionNode)parent; + if (mae.getRightOperandNode() == this && mae.getLeftOperandNode().getNodeID() == ASTNodeID.IdentifierID) + { + // if the member access expression left side is not an identifier + IDefinition parentDef = mae.getLeftOperandNode().resolveType(project); + if (parentDef instanceof IClassDefinition) + { + ((RoyaleProject)project).addToAPIReport((IClassDefinition)parentDef, result); + } + else + { + ((RoyaleProject)project).addToAPIReport(result); + } + } + else + { + ((RoyaleProject)project).addToAPIReport(result); + } + } + else + { + ((RoyaleProject)project).addToAPIReport(result); + } + } + else + ((RoyaleProject)project).addToAPIReport(result); + } + return result; } -- To stop receiving notification emails like this one, please contact aha...@apache.org.