1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jshell;
  27 
  28 import jdk.jshell.Wrap.CompoundWrap;
  29 import static jdk.jshell.Util.*;
  30 import java.util.Locale;
  31 import javax.tools.Diagnostic;
  32 import javax.tools.JavaFileObject;
  33 import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject;
  34 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
  35 
  36 /**
  37  *
  38  * @author Robert Field
  39  */
  40 final class OuterWrap implements GeneralWrap {
  41 
  42     private final String packageName;
  43     private final String className;
  44     private final String userSource;
  45     private final GeneralWrap w;
  46     private final Wrap guts;
  47 
  48     public static OuterWrap wrapInClass(String packageName, String className,
  49              String imports, String userSource, Wrap guts) {
  50         GeneralWrap kw = new CompoundWrap(
  51                 imports
  52                 + "class " + className + " {\n",
  53                 guts,
  54                 "}\n");
  55         return new OuterWrap(packageName, className, userSource, kw, guts);
  56     }
  57 
  58     public static OuterWrap wrapImport(String userSource, Wrap guts) {
  59         return new OuterWrap("", "", userSource, guts, guts);
  60     }
  61 
  62     private OuterWrap(String packageName, String className, String userSource,
  63             GeneralWrap w, Wrap guts) {
  64         this.packageName = packageName;
  65         this.className = className;
  66         this.userSource = userSource;
  67         this.w = w;
  68         this.guts = guts;
  69     }
  70 
  71     @Override
  72     public final String wrapped() {
  73         return w.wrapped();
  74     }
  75 
  76     @Override
  77     public int snippetIndexToWrapIndex(int ui) {
  78         return w.snippetIndexToWrapIndex(ui);
  79     }
  80 
  81     @Override
  82     public int wrapIndexToSnippetIndex(int si) {
  83         return w.wrapIndexToSnippetIndex(si);
  84     }
  85 
  86     @Override
  87     public int firstSnippetIndex() {
  88         return w.firstSnippetIndex();
  89     }
  90 
  91     @Override
  92     public int lastSnippetIndex() {
  93         return w.lastSnippetIndex();
  94     }
  95 
  96     @Override
  97     public int snippetLineToWrapLine(int snline) {
  98         return w.snippetLineToWrapLine(snline);
  99     }
 100 
 101     @Override
 102     public int wrapLineToSnippetLine(int wline) {
 103         return w.wrapLineToSnippetLine(wline);
 104     }
 105 
 106     @Override
 107     public int firstSnippetLine() {
 108         return w.firstSnippetLine();
 109     }
 110 
 111     @Override
 112     public int lastSnippetLine() {
 113         return w.lastSnippetLine();
 114     }
 115 
 116     public String className() {
 117         return className;
 118     }
 119 
 120     public String classFullName() {
 121         return packageName + "." + className;
 122     }
 123 
 124     public String getUserSource() {
 125         return userSource;
 126     }
 127 
 128     Wrap guts() {
 129         return guts;
 130     }
 131 
 132     Diag wrapDiag(Diagnostic<? extends JavaFileObject> d) {
 133         return new WrappedDiagnostic(d);
 134     }
 135 
 136     class WrappedDiagnostic extends Diag {
 137 
 138         private final Diagnostic<? extends JavaFileObject> diag;
 139 
 140         WrappedDiagnostic(Diagnostic<? extends JavaFileObject> diag) {
 141             this.diag = diag;
 142         }
 143 
 144         @Override
 145         public boolean isError() {
 146             return diag.getKind() == Diagnostic.Kind.ERROR;
 147         }
 148 
 149         @Override
 150         public long getPosition() {
 151             return wrapIndexToSnippetIndex(diag.getPosition());
 152         }
 153 
 154         @Override
 155         public long getStartPosition() {
 156             return wrapIndexToSnippetIndex(diag.getStartPosition());
 157         }
 158 
 159         @Override
 160         public long getEndPosition() {
 161             return wrapIndexToSnippetIndex(diag.getEndPosition());
 162         }
 163 
 164         @Override
 165         public String getCode() {
 166             return diag.getCode();
 167         }
 168 
 169         @Override
 170         public String getMessage(Locale locale) {
 171             return expunge(diag.getMessage(locale));
 172         }
 173 
 174         @Override
 175         Unit unitOrNull() {
 176             JavaFileObject fo = diag.getSource();
 177             if (fo instanceof SourceMemoryJavaFileObject) {
 178                 SourceMemoryJavaFileObject sfo = (SourceMemoryJavaFileObject) fo;
 179                 if (sfo.getOrigin() instanceof Unit) {
 180                     return (Unit) sfo.getOrigin();
 181                 }
 182             }
 183             return null;
 184         }
 185 
 186         @Override
 187         boolean isResolutionError() {
 188             if (!super.isResolutionError()) {
 189                 return false;
 190             }
 191             for (String line : diag.getMessage(PARSED_LOCALE).split("\\r?\\n")) {
 192                 if (line.trim().startsWith("location:")) {
 193                     if (!line.contains(REPL_CLASS_PREFIX)) {
 194                         // Resolution error must occur within a REPL class or it is not resolvable
 195                         return false;
 196                     }
 197                 }
 198             }
 199             return true;
 200         }
 201 
 202         @Override
 203         public String toString() {
 204             return "WrappedDiagnostic(" + getMessage(null) + ":" + getPosition() + ")";
 205         }
 206     }
 207 }