All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.spi.java.queries.CompilerOptionsQueryImplementation Maven / Gradle / Ivy

The newest version!
/*
 * 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.netbeans.spi.java.queries;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.ChangeListener;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.URLMapper;

/**
 * Permits providers to return explicit compiler options for Java source file.
 * @author Tomas Zezula
 * @since 1.64
 */
public interface CompilerOptionsQueryImplementation {

    /**
     * Returns explicit compiler options for the given Java file, Java package or source folder.
     * @param file the Java source file, Java package or source folder in question
     * @return a {@link Result} object encapsulating the compiler options or null
     * when the file is unknown to the provider
     */
    @CheckForNull
    Result getOptions(@NonNull final FileObject file);

    /**
     * Result of finding compiler options, encapsulating the answer as well as the
     * ability to listen to it.
     */
    public abstract static class Result {
        private static final Logger LOG = Logger.getLogger(CompilerOptionsQueryImplementation.class.getName());

        /**
         * Gets the explicit compiler options.
         * @return the list of the compiler options
         */
        @NonNull
        public abstract List getArguments();

        /**
         * Add a listener to changes of compiler options.
         * @param listener a listener to add
         */
        public abstract void addChangeListener(@NonNull final ChangeListener listener);

        /**
         * Remove a listener to changes of compiler options.
         * @param listener a listener to remove
         */
        public abstract void removeChangeListener(@NonNull final ChangeListener listener);

        /**
         * Utility method the tokenize the command line into individual arguments.
         * @param commandLine the command line to be tokenized
         * @return a list of command line arguments
         */
        protected final List parseLine(@NonNull final String commandLine) {
            return doParseLine(commandLine, null);
        }

        /**
         * Utility method the tokenize the command line into individual arguments.
         * @param commandLine the command line to be tokenized
         * @param workingDirectory if set to null, argument files will not be supported;
         *                         if non-null, argument file names will be resolved relative to this directory
         * @return a list of command line arguments
         * @since 1.92
         */
        protected final List parseLine(@NonNull final String commandLine,
                                               @NullAllowed URI workingDirectory) {
            return doParseLine(commandLine, workingDirectory);
        }

        static List doParseLine(@NonNull final String commandLine,
                                        @NullAllowed URI workingDirectory) {
            final List result = new ArrayList<>();
            StringBuilder current = new StringBuilder();
            boolean escape = false, doubleQuote = false, quote = false;
            Consumer defaultHandleOption = result::add;
            Consumer handleOption = defaultHandleOption;
            for (int i = 0; i < commandLine.length(); i++) {
                final char c = commandLine.charAt(i);
                switch (c) {
                    case '\\':  //NOI18N
                        if (!quote) {
                            escape = !escape;
                        }
                        break;
                    case '\'':  //NOI18N
                        if (!escape && !doubleQuote) {
                            quote = !quote;
                        }
                        escape = false;
                        break;
                    case '"':   //NOI18N
                        if (!escape && !quote) {
                            doubleQuote = !doubleQuote;
                        }
                        escape = false;
                        break;
                    case ' ':   //NOI18N
                    case '\t':  //NOI18N
                        if (!escape && !quote && !doubleQuote) {
                            if (current.length() > 0) {
                                handleOption.accept(current.toString());
                                handleOption = defaultHandleOption;
                                current = new StringBuilder();
                            }
                        } else {
                            current.append(c);
                        }
                        escape = false;
                        break;
                    case '@':
                        if (workingDirectory != null && i + 1 < commandLine.length() && commandLine.charAt(i + 1) != '@' && current.length() == 0) {
                            handleOption = path -> {
                                try {
                                    URI resolved = workingDirectory.resolve(path);
                                    FileObject file = URLMapper.findFileObject(resolved.toURL());
                                    if (file == null) {
                                        LOG.log(Level.FINE, "URI {0}, resolved to {1}, did not yield an existing file", new Object[] {path, resolved.toString()});
                                        result.add("@" + path);
                                        return ;
                                    }
                                    for (String line : file.asLines()) {
                                        result.addAll(doParseLine(line, null));
                                    }
                                } catch (IOException ex) {
                                    LOG.log(Level.FINE, null, ex);
                                }
                            };
                            break;
                        }
                        //fall-through
                    default:
                        current.append(c);
                        escape = false;
                        break;
                }
            }
            if (current.length() > 0) {
                handleOption.accept(current.toString());
            }
            return Collections.unmodifiableList(result);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy