Package com.android.tools.lint

Source Code of com.android.tools.lint.EcjParser$LocationHandle

/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed 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 com.android.tools.lint;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.tools.lint.client.api.IJavaParser;
import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.detector.api.JavaContext;
import com.android.tools.lint.detector.api.Location;

import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;

import java.io.File;
import java.util.List;

import lombok.ast.Node;
import lombok.ast.TypeReference;
import lombok.ast.ecj.EcjTreeConverter;

/**
* Java parser which uses ECJ for parsing.
*/
public class EcjParser implements IJavaParser {
    private final Parser mParser;

    private final LintClient mClient;

    public EcjParser(LintClient client) {
        mClient = client;
        CompilerOptions options = new CompilerOptions();
        // Always using JDK 7 rather than basing it on project metadata since we
        // don't do compilation error validation in lint (we leave that to the IDE's
        // error parser or the command line build's compilation step); we want an
        // AST that is as tolerant as possible.
        options.complianceLevel = ClassFileConstants.JDK1_7;
        options.sourceLevel = ClassFileConstants.JDK1_7;
        options.targetJDK = ClassFileConstants.JDK1_7;
        options.parseLiteralExpressionsAsConstants = true;
        ProblemReporter problemReporter = new ProblemReporter(
                DefaultErrorHandlingPolicies.exitOnFirstError(),
                options,
                new DefaultProblemFactory());
        mParser = new Parser(problemReporter, options.parseLiteralExpressionsAsConstants);
        mParser.javadocParser.checkDocComment = false;
    }

    @Override
    public lombok.ast.Node parseJava(@NonNull JavaContext context) {
        // Use Eclipse's compiler
        EcjTreeConverter converter = new EcjTreeConverter();
        String code = context.getContents();
        if (code == null) {
            return null;
        }

        CompilationUnit sourceUnit = new CompilationUnit(code.toCharArray(),
                context.file.getName(), "UTF-8"); //$NON-NLS-1$
        CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
        CompilationUnitDeclaration unit;
        try {
            unit = mParser.parse(sourceUnit, compilationResult);
        } catch (AbortCompilation e) {
            // No need to report Java parsing errors while running in Eclipse.
            // Eclipse itself will already provide problem markers for these files,
            // so all this achieves is creating "multiple annotations on this line"
            // tooltips instead.
            return null;
        }
        if (unit == null) {
            return null;
        }

        try {
            converter.visit(code, unit);
            List<? extends Node> nodes = converter.getAll();

            // There could be more than one node when there are errors; pick out the
            // compilation unit node
            for (lombok.ast.Node node : nodes) {
                if (node instanceof lombok.ast.CompilationUnit) {
                    return node;
                }
            }

            return null;
        } catch (Throwable t) {
            mClient.log(t, "Failed converting ECJ parse tree to Lombok for file %1$s",
                    context.file.getPath());
            return null;
        }
    }

    @NonNull
    @Override
    public Location getLocation(@NonNull JavaContext context,
            @NonNull lombok.ast.Node node) {
        lombok.ast.Position position = node.getPosition();
        return Location.create(context.file, context.getContents(),
                position.getStart(), position.getEnd());
    }

    @NonNull
    @Override
    public
    Location.Handle createLocationHandle(@NonNull JavaContext context,
            @NonNull lombok.ast.Node node) {
        return new LocationHandle(context.file, node);
    }

    @Override
    public void dispose(@NonNull JavaContext context,
            @NonNull lombok.ast.Node compilationUnit) {
    }

    @Override
    @Nullable
    public lombok.ast.Node resolve(@NonNull JavaContext context,
            @NonNull lombok.ast.Node node) {
        return null;
    }

    @Override
    @Nullable
    public TypeReference getType(@NonNull JavaContext context, @NonNull lombok.ast.Node node) {
        return null;
    }

    /* Handle for creating positions cheaply and returning full fledged locations later */
    private static class LocationHandle implements Location.Handle {
        private File mFile;
        private lombok.ast.Node mNode;
        private Object mClientData;

        public LocationHandle(File file, lombok.ast.Node node) {
            mFile = file;
            mNode = node;
        }

        @NonNull
        @Override
        public Location resolve() {
            lombok.ast.Position pos = mNode.getPosition();
            return Location.create(mFile, null /*contents*/, pos.getStart(), pos.getEnd());
        }

        @Override
        public void setClientData(@Nullable Object clientData) {
            mClientData = clientData;
        }

        @Override
        @Nullable
        public Object getClientData() {
            return mClientData;
        }
    }
}
TOP

Related Classes of com.android.tools.lint.EcjParser$LocationHandle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.