blob: f99c287c0ef6bdc638ef9cb59052d80bb1da3c1b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.royale.compiler.tools.annotate;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
public class OrderSwitches
{
public static void processFile(File file) throws AnnotateClass.AnnotateClassDeleteException, AnnotateClass.AnnotateClassRenameException {
if(!file.exists()) {
System.out.println("Missing file: " + file.getPath());
return;
}
try
{
// Prepare to read the file.
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
File tmpOutputFile = new File(file.getParentFile(), file.getName() + ".tmp");
FileOutputStream fileOutputStream = new FileOutputStream(tmpOutputFile);
PrintStream outputStream = new PrintStream(fileOutputStream);
try
{
// Read it line-by-line.
String line;
ArrayList<String> lines = new ArrayList<String>();
boolean inSwitch = false;
while ((line = bufferedReader.readLine()) != null)
{
if (line.contains("The following code was generated by JFlex "))
{
int c = line.indexOf(" on ");
if (c != -1)
line = line.substring(0, c) + " */";
}
if (line.contains("* on ") && line.contains("from the specification file"))
line = " * from the specification file";
if (line.contains("<tt>") && line.contains("compiler/src/main/jflex"))
{
int t = line.indexOf("<tt>");
int rc = line.indexOf("compiler/src/main/jflex");
line = line.substring(0, t + 4) + line.substring(rc);
}
// If the line starts with "switch", and the cases are numbers, make sure they are in order.
if (line.contains(" switch (zzAction")) {
inSwitch = true;
System.out.println("Ordering Switch in file: " + file.getPath());
}
if (inSwitch)
{
lines.add(line);
if (line.startsWith(" }")) {
orderSwitch(lines);
for (String orderedLine : lines)
{
outputStream.println(orderedLine);
}
inSwitch = false;
}
}
else
outputStream.println(line);
}
}
finally
{
try {
bufferedReader.close();
} catch(Exception e) {
// Ignore.
}
try {
outputStream.close();
} catch(Exception e) {
// Ignore.
}
try {
fileOutputStream.close();
} catch(Exception e) {
// Ignore.
}
try {
inputStreamReader.close();
} catch(Exception e) {
// Ignore.
}
try {
fileInputStream.close();
} catch(Exception e) {
// Ignore.
}
}
// Remove the original file.
if(!file.delete()) {
// wait a bit then retry on Windows
if (file.exists())
{
for (int i = 0; i < 6; i++)
{
Thread.sleep(500);
System.gc();
if (file.delete())
break;
}
if (file.exists())
throw new AnnotateClass.AnnotateClassDeleteException("Error deleting original file at: " + file.getPath());
}
}
// Rename the temp file to the name of the original file.
if(!tmpOutputFile.renameTo(file)) {
throw new AnnotateClass.AnnotateClassRenameException("Error renaming the temp file from: " + tmpOutputFile.getPath() +
" to: " + file.getPath());
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void orderSwitch(ArrayList<String> lines) {
HashMap<String,List<String>> switchMap = new HashMap<String,List<String>>();
ArrayList<String> defaultCase = new ArrayList<String>();
ArrayList<String> breaks = new ArrayList<String>();
String line0 = lines.get(0); // first line should be switch statement
boolean inDefault = false;
int n = lines.size();
for (int i = 1; i < n; i++)
{
String line = lines.get(i);
int c = line.indexOf(" case ");
if (!inDefault && (c != -1))
{
String cayse = line.substring(c);
if (line.contains("break;"))
{
// some cases just contain a break statement.
// the are used to make sure the prior case
// ends with a break without having to check
// if the break statement would be reachable
// due to return statements in the case.
breaks.add(line);
continue;
}
else
{
ArrayList<String> caseLines = new ArrayList<String>();
for (int j = i + 1; j < n; j++)
{
line = lines.get(j);
if (line.contains(" case "))
{
switchMap.put(cayse, caseLines);
i = j - 1;
break;
}
else if (line.contains("default:"))
{
switchMap.put(cayse, caseLines);
inDefault = true;
i = j;
// assumes no break at end of default case
defaultCase.add(line);
break;
}
caseLines.add(line);
}
}
}
else if (line.contains("default:"))
{
inDefault = true;
// assumes no break at end of default case
defaultCase.add(line);
}
else if (inDefault)
defaultCase.add(line);
}
Set<String> keys = switchMap.keySet();
ArrayList<String> keyList = new ArrayList<String>();
keyList.addAll(keys);
Collections.sort(keyList);
lines.clear();
lines.add(line0);
int breakIndex = 0;
for (String key : keyList)
{
lines.add(" " + key);
List<String> caseLines = switchMap.get(key);
lines.addAll(caseLines);
lines.add(breaks.get(breakIndex++));
}
boolean inSwitch = false;
boolean sawDefault = false;
ArrayList<String> switchLines = new ArrayList<String>();
for (String defaultLine : defaultCase)
{
// If the line starts with "switch", and the cases are numbers, make sure they are in order.
if (defaultLine.contains("switch (zzLexicalState)")) {
inSwitch = true;
System.out.println("Ordering Switch in default: ");
}
if (inSwitch)
{
switchLines.add(defaultLine);
if (defaultLine.contains("default:"))
sawDefault = true;
if (sawDefault && defaultLine.startsWith(" }")) {
orderSwitch(switchLines);
for (String orderedLine : switchLines)
{
lines.add(orderedLine);
}
inSwitch = false;
}
}
else
lines.add(defaultLine);
}
}
public static void main(String[] args)
{
File f = new File(args[0]);
try {
processFile(f);
} catch (Exception e) {
e.printStackTrace();
}
}
}