1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.lint; 18 19 import com.android.annotations.Nullable; 20 import com.android.tools.lint.client.api.IJavaParser; 21 import com.android.tools.lint.detector.api.JavaContext; 22 import com.android.tools.lint.detector.api.Location; 23 import com.android.tools.lint.detector.api.Location.Handle; 24 25 import java.io.File; 26 import java.util.List; 27 28 import lombok.ast.CompilationUnit; 29 import lombok.ast.Node; 30 import lombok.ast.Position; 31 import lombok.ast.grammar.ParseProblem; 32 import lombok.ast.grammar.Source; 33 34 /** 35 * Java parser which uses the Lombok parser directly. This is a pretty slow parser 36 * (2.5 times slower than javac, which in turn is about 3 times slower than EJC for 37 * some benchmarks). 38 */ 39 public class LombokParser implements IJavaParser { 40 41 @Override parseJava(JavaContext context)42 public Node parseJava(JavaContext context) { 43 try { 44 Source source = new Source(context.getContents(), context.file.getName()); 45 List<Node> nodes = source.getNodes(); 46 47 // Don't analyze files containing errors 48 List<ParseProblem> problems = source.getProblems(); 49 if (problems != null && problems.size() > 0) { 50 /* Silently ignore the errors. There are still some bugs in Lombok/Parboiled 51 * (triggered if you run lint on the AOSP framework directory for example), 52 * and having these show up as fatal errors when it's really a tool bug 53 * is bad. To make matters worse, the error messages aren't clear: 54 * http://code.google.com/p/projectlombok/issues/detail?id=313 55 for (ParseProblem problem : problems) { 56 Position position = problem.getPosition(); 57 Location location = Location.create(context.file, 58 context.getContents(), position.getStart(), position.getEnd()); 59 // Sanitize the message? 60 // See http://code.google.com/p/projectlombok/issues/detail?id=313 61 String message = problem.getMessage(); 62 context.report( 63 IssueRegistry.PARSER_ERROR, location, 64 message, 65 null); 66 67 } 68 */ 69 return null; 70 } 71 72 // There could be more than one node when there are errors; pick out the 73 // compilation unit node 74 for (Node node : nodes) { 75 if (node instanceof CompilationUnit) { 76 return node; 77 } 78 } 79 return null; 80 } catch (Throwable e) { 81 /* Silently ignore the errors. There are still some bugs in Lombok/Parboiled 82 * (triggered if you run lint on the AOSP framework directory for example), 83 * and having these show up as fatal errors when it's really a tool bug 84 * is bad. To make matters worse, the error messages aren't clear: 85 * http://code.google.com/p/projectlombok/issues/detail?id=313 86 context.report( 87 IssueRegistry.PARSER_ERROR, Location.create(context.file), 88 e.getCause() != null ? e.getCause().getLocalizedMessage() : 89 e.getLocalizedMessage(), 90 null); 91 */ 92 93 return null; 94 } 95 } 96 97 @Override getLocation(JavaContext context, lombok.ast.Node node)98 public Location getLocation(JavaContext context, lombok.ast.Node node) { 99 lombok.ast.Position position = node.getPosition(); 100 return Location.create(context.file, context.getContents(), 101 position.getStart(), position.getEnd()); 102 } 103 104 @Override createLocationHandle(JavaContext context, Node node)105 public Handle createLocationHandle(JavaContext context, Node node) { 106 return new LocationHandle(context.file, node); 107 } 108 109 @Override dispose(JavaContext context, Node compilationUnit)110 public void dispose(JavaContext context, Node compilationUnit) { 111 } 112 113 /* Handle for creating positions cheaply and returning full fledged locations later */ 114 private class LocationHandle implements Handle { 115 private File mFile; 116 private Node mNode; 117 private Object mClientData; 118 LocationHandle(File file, Node node)119 public LocationHandle(File file, Node node) { 120 mFile = file; 121 mNode = node; 122 } 123 124 @Override resolve()125 public Location resolve() { 126 Position pos = mNode.getPosition(); 127 return Location.create(mFile, null /*contents*/, pos.getStart(), pos.getEnd()); 128 } 129 130 131 @Override setClientData(@ullable Object clientData)132 public void setClientData(@Nullable Object clientData) { 133 mClientData = clientData; 134 } 135 136 @Override 137 @Nullable getClientData()138 public Object getClientData() { 139 return mClientData; 140 } 141 } 142 } 143