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

manifold.internal.javac.ManParserFactory_8 Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2019 - Manifold Systems LLC
 *
 * 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 manifold.internal.javac;

import com.sun.source.util.TaskEvent;
import com.sun.tools.javac.parser.*;
import com.sun.tools.javac.util.Context;
import java.nio.CharBuffer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.tools.JavaFileObject;

import manifold.util.JreUtil;
import manifold.util.ReflectUtil;


import static com.sun.tools.javac.parser.Tokens.TokenKind.STRINGLITERAL;

/**
 * Override ParserFactory to:
* - facilitate a pluggable Java preprocessor
* - handle inlined file fragments in comment tokens
*/ public class ManParserFactory_8 extends ParserFactory implements ParserFactoryFiles { private TaskEvent _taskEvent; private final Preprocessor _preprocessor; public static ManParserFactory_8 instance( Context ctx ) { ParserFactory parserFactory = ctx.get( parserFactoryKey ); if( !(parserFactory instanceof ManParserFactory_8) ) { ctx.put( parserFactoryKey, (ParserFactory)null ); parserFactory = new ManParserFactory_8( ctx ); } return (ManParserFactory_8)parserFactory; } private ManParserFactory_8( Context ctx ) { super( ctx ); _preprocessor = Preprocessor.instance( ctx ); ReflectUtil.field( this, "scannerFactory" ).set( ManScannerFactory.instance( ctx, this ) ); } @Override public JavacParser newParser( CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap ) { return newParser( input, keepDocComments, keepEndPos, keepLineMap, false ); } //override Java 9+ @SuppressWarnings("unused") public JavacParser newParser( CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo ) { input = _preprocessor.process( _taskEvent.getSourceFile(), input ); mapInput( _taskEvent.getSourceFile(), input ); Lexer lexer = ((ScannerFactory)ReflectUtil.field( this, "scannerFactory" ).get()).newScanner(input, keepDocComments); return (JavacParser)ReflectUtil.constructor( "com.sun.tools.javac.parser.ManJavacParser", ParserFactory.class, Lexer.class, boolean.class, boolean.class, boolean.class, boolean.class ) .newInstance( this, lexer, keepDocComments, keepLineMap, keepEndPos, parseModuleInfo ); } private void mapInput( JavaFileObject sourceFile, CharSequence input ) { fileToProcessedInput.put( sourceFile.getName(), input ); } @Override public void setTaskEvent( TaskEvent e ) { _taskEvent = e; } /** * Override ScannerFactory so we can examine tokens as they are read. This is purely a performance measure to avoid * having to tokenize each source file twice. */ public static class ManScannerFactory extends ScannerFactory { private final ManParserFactory_8 _parserFactory; public static ScannerFactory instance( Context ctx, ManParserFactory_8 parserFactory ) { ScannerFactory scannerFactory = ctx.get( scannerFactoryKey ); if( !(scannerFactory instanceof ManScannerFactory) ) { ctx.put( scannerFactoryKey, (ScannerFactory)null ); scannerFactory = new ManScannerFactory( ctx, parserFactory ); } return scannerFactory; } private ManScannerFactory( Context ctx, ManParserFactory_8 parserFactory ) { super( ctx ); _parserFactory = parserFactory; } public Scanner newScanner( CharSequence input, boolean keepDocComments ) { if( input instanceof CharBuffer ) { CharBuffer buf = (CharBuffer)input; if( keepDocComments ) { return new ManScanner( this, new ManJavadocTokenizer( this, buf ) ); } else { return new ManScanner( this, buf ); } } else { char[] array = input.toString().toCharArray(); return newScanner( array, array.length, keepDocComments ); } } public Scanner newScanner( char[] input, int inputLength, boolean keepDocComments ) { if( keepDocComments ) { return new ManScanner( this, new ManJavadocTokenizer( this, input, inputLength ) ); } else { return new ManScanner( this, input, inputLength ); } } private class ManJavadocTokenizer extends JavadocTokenizer { private final ManScannerFactory _scannerFactory; private final UnicodeReader _reader; ManJavadocTokenizer( ManScannerFactory manScannerFactory, CharBuffer buf ) { super( manScannerFactory, buf ); _scannerFactory = manScannerFactory; //noinspection ConstantConditions _reader = JreUtil.isJava16orLater() ? (UnicodeReader)(Object)this : reader(); } private UnicodeReader reader() { return (UnicodeReader)ReflectUtil.field( this, "reader" ).get(); } ManJavadocTokenizer( ManScannerFactory manScannerFactory, char[] input, int inputLength ) { super( manScannerFactory, input, inputLength ); _scannerFactory = manScannerFactory; //noinspection ConstantConditions _reader = JreUtil.isJava16orLater() ? (UnicodeReader)(Object)this : reader(); } protected Tokens.Comment processComment( int pos, int endPos, Tokens.Comment.CommentStyle style ) { Tokens.Comment comment = super.processComment( pos, endPos, style ); char[] buf = _reader.getRawCharacters( pos, endPos ); FragmentProcessor.instance().processComment( _scannerFactory._parserFactory._taskEvent.getSourceFile(), pos, new String( buf ), style ); return comment; } public Tokens.Token readToken() { Tokens.Token token = super.readToken(); if( token.kind == STRINGLITERAL ) { // todo: passing raw characters means we must parse string literal escaped chars esp. '"', '\n', unicode char[] buf = _reader.getRawCharacters( token.pos, token.endPos ); FragmentProcessor.instance().processString( ((ManScannerFactory)ReflectUtil.field( this, "fac" ).get())._parserFactory._taskEvent.getSourceFile(), token.pos, new String( buf ) ); } return token; } } private static class ManScanner extends Scanner { ManScanner( ManScannerFactory manScannerFactory, JavaTokenizer manJavadocTokenizer ) { super( manScannerFactory, manJavadocTokenizer ); } ManScanner( ManScannerFactory fac, char[] buf, int len ) { this( fac, new ManJavaTokenizer( fac, buf, len ) ); } ManScanner( ManScannerFactory fac, CharBuffer buf ) { this( fac, new ManJavaTokenizer( fac, buf ) ); } private static class ManJavaTokenizer extends JavaTokenizer { private final UnicodeReader _reader; ManJavaTokenizer( ManScannerFactory fac, char[] buf, int len ) { super( fac, buf, len ); //noinspection ConstantConditions _reader = JreUtil.isJava16orLater() ? (UnicodeReader)(Object)this : reader(); } ManJavaTokenizer( ManScannerFactory fac, CharBuffer buf ) { super( fac, buf ); //noinspection ConstantConditions _reader = JreUtil.isJava16orLater() ? (UnicodeReader)(Object)this : reader(); } private UnicodeReader reader() { return (UnicodeReader)ReflectUtil.field( this, "reader" ).get(); } protected Tokens.Comment processComment( int pos, int endPos, Tokens.Comment.CommentStyle style ) { Tokens.Comment comment = super.processComment( pos, endPos, style ); char[] buf = _reader.getRawCharacters( pos, endPos ); FragmentProcessor.instance().processComment( ((ManScannerFactory)fac)._parserFactory._taskEvent.getSourceFile(), pos, new String( buf ), style ); return comment; } public Tokens.Token readToken() { Tokens.Token token = super.readToken(); if( token.kind == STRINGLITERAL ) { char[] buf = _reader.getRawCharacters( token.pos, token.endPos ); FragmentProcessor.instance().processString( ((ManScannerFactory)fac)._parserFactory._taskEvent.getSourceFile(), token.pos, new String( buf ) ); } return token; } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy