aboutsummaryrefslogtreecommitdiff
path: root/javascript/app/utils/go-to-definition.js
blob: e05f6bf581355f2bcdd56bafd5f66d7320dce218 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
function exactLocationToUrl(exactLocation) {
  const modulePath = exactLocation.modulePath;
  const packageId = exactLocation.packageId.name + "-" + exactLocation.packageId.version;
  let hash = "";
  if(exactLocation.startLine != 1) {
    hash = "#L" + exactLocation.startLine;
  }
  return "/package/"+packageId+"/show/"+modulePath+hash;
}

function hackageUrl(packageId,locationInfo) {
  const dasherizedModuleName = locationInfo.moduleName.replace(/\./g,'-');
  let key;
  if(locationInfo.entity === "Val") {
    key = "v";
  } else {
    key = "t";
  }  
  let hash = "";
  if(locationInfo.entity === "Val" || locationInfo.entity === "Typ") {
    hash = "#"+key+":"+locationInfo.haddockAnchorId;
  }   
  return "https://hackage.haskell.org/package/"+packageId+"/docs/"+dasherizedModuleName+".html"+hash;
}

function openUrl(buttonId,url) {  
  if(buttonId === 2) {//middle mouse button
    window.open(url, '_blank');
  } else if(buttonId == 1) {//left mouse button
    window.location = url;
  }
  return false;
}

function saveCurrentLocation(currentLineNumber) {  
  if(currentLineNumber) {
    const url = window.location.origin + window.location.pathname + "#L" + currentLineNumber;    
    if(location.href != url) {      
      window.location.hash = "#L" + currentLineNumber;
    }
  }
}

function goToDefinition(store,locationInfo,buttonId,currentLineNumber) {
  if(locationInfo.tag === "ExactLocation") {
    const url = exactLocationToUrl(locationInfo);
    if(locationInfo.startLine !== currentLineNumber) {
      saveCurrentLocation(currentLineNumber);
    }
    openUrl(buttonId,url);
  } else if(locationInfo.tag === "ApproximateLocation") {    
    const packageId = locationInfo.packageId.name+"-"+locationInfo.packageId.version;    
    if(locationInfo.entity === "Mod") {
      store.loadDefinitionSite(packageId,
                               locationInfo.moduleName,
                               locationInfo.componentId,
                               locationInfo.entity,
                               locationInfo.moduleName)
        .then((defSite) => {
          const packageId = defSite.location.packageId.name + "-" + defSite.location.packageId.version;
          openUrl(buttonId,"/package/" + packageId + "/show/" + defSite.location.modulePath);
        }).catch(() => {
          openUrl(buttonId,hackageUrl(packageId,locationInfo));
        });      
    } else {
    store.loadDefinitionSite(packageId,
                            locationInfo.moduleName,
                            locationInfo.componentId,
                            locationInfo.entity,
                            locationInfo.name)
      .then((definitionSite) => {
        if(definitionSite.location.tag === "ExactLocation") {
          const url = exactLocationToUrl(definitionSite.location);
          if(locationInfo.startLine !== currentLineNumber) {
            saveCurrentLocation(currentLineNumber);
          }
          openUrl(buttonId,url);
        } else {
          saveCurrentLocation(currentLineNumber);
          openUrl(buttonId,hackageUrl(packageId,locationInfo));
        }
      }).catch((e) => {
        console.log(e);
        saveCurrentLocation(currentLineNumber);
        openUrl(buttonId,hackageUrl(packageId,locationInfo));
      });
    }    
  } else {
    alert('No location info');
  }  
}

export {
  goToDefinition,openUrl
}